require "Common/define"
require "Logic/Config"
require "Common/functions"
require "Logic/ZZMathBit"
require "Logic/PetManager"
require "Battle/Entity/Entity"
---@class HeroManager
HeroManager = {
    firstRankCityShowPlayer = { id = "0", name = "" }
};
local this = HeroManager;
local type = type
local attributeLibCfg = nil;
local heroCfg = nil;
local charactorExpConfig = nil;
local tabAllHero = {};
local tabKeyMap = {};
local allHeroPetAttrDirty = {};
local fetterGroup = {}--key:modelId value:{所有羁绊信息}
local mySelfId = nil; --(废弃)
local mySelfModelId = nil --临时变量 兼容处理 后期干掉
local tableHandbook = {} -- 图鉴
local crystalInfo; -- 水晶信息(level,exp)
local tabFetter = {}--已解锁的羁绊
local tabOwner = {};
local tabUnOwner = {};
local fetterHadAwardTable;

local heroAdds = { 0, 0, 0, 0, 0, 0 };--布阵英雄加成等级

local settleTime; -- 上次结算时间
local quickTimes; --已快速战斗次数
local limitStarNum = 0;
local upPoolNum = 0;
local upPool1 = nil;
local upPool2 = nil;
local upPool3 = nil;
local upPool4 = nil;
local upPool5 = nil;
local upPool6 = nil;
local upPool7 = nil;
local upPool8 = nil;
--local upPool = {};
local obj;
local CurrentTrammelPoint = 0   --当前羁绊点
local timer
this.HeroTypeList = { 6, 3, 2, 5, 1, 4 }
local winshHeroData = nil
local drawCount = 0
local wishHasNum = {}
this.allVipNum = 0
this.hasVipNum = 0
this.extraHeros = {}
this.extraNum = nil
this.extraHasHeroIds = {}
this._factionSortList = { 0, 2, 3, 1 } -- 势力排序,大的在前, 其他,神,魔,蔷薇
this.lvColors = nil
local insureRemain = 0
local beforePower = 0
local afterPower = 0
local attrTable = {}
local combinationShowInfo = {};--英雄羁绊客户端表
local combinationInfo = {};--英雄羁绊服务端表

-- Data Layer
local fetterAttrList = {}
local fetterPower = 0
local heroLimitCfg = nil; -- 英雄延迟开放
----------------------
this.heroInteractionNum = 0
--HeroManager.roleInfo = {}
HeroManager.HeroSortType = {
    power = 1,
    quality = 2,
    level = 3,
    --link=4,
    totalNumber = 3,
}
HeroManager.firstHeroPartnerId = nil;
function HeroManager.init()
    this.lvColors = {[0]="#D3D9DD",[1] = "#C8AA96",[2] ="#94F028",[3] = "#FFF2BA"}
    attributeLibCfg = G.dataTable["t_attributelibrary"];
    heroCfg = G.dataTable["t_hero"];
    charactorExpConfig = G.dataTable["t_characterexp"];
    heroLimitCfg = G.dataTable["t_herolimit"];

    this.initHeroBaseInfo();
    crystalInfo = {};
    crystalInfo.level = 1;
    crystalInfo.exp = 0;
    this.changePic = 0
    HeroManager.sortType = 1;--英雄排序类型
    if GetPlayerPrefs("CharactorMainSortOrder") then
        HeroManager.sortType = tonumber(GetPlayerPrefs("CharactorMainSortOrder"));
    end

    combinationShowInfo = G.dataTable["t_herocombinationshow"];
    combinationInfo = G.dataTable["t_herocombination"];

    --初始化根据modelId取得的羁绊信息
    local fetterDetailCfg = G.dataTable["t_trammel"]
    fetterGroup = {}
    for _, info in pairs(fetterDetailCfg) do
        if fetterGroup[info.f_HeroID] == nil then
            fetterGroup[info.f_HeroID] = {};
        end
        table.insert(fetterGroup[info.f_HeroID], info);
        table.sort(fetterGroup[info.f_HeroID], function(a, b)
            return a["f_Id"] < b["f_Id"]
        end)
    end
    --table.clear(tabAllHero)
    --table.clear(tabKeyMap)
    this.notShowHeroChooseFightTypeMap = {};
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.ArenaDef] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.FriendAttack] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.FriendDefend] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.DarkStreet] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.PlunderBattle] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.GuildBoss] = true;
    --this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.FriendCompeteBattle] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.CrossArenaDef] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.TeamCrossArenaDef] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.FormationEditor] = true;
    this.notShowHeroChooseFightTypeMap[EnumConst.FormationType.RankBattle] = true;
end

function HeroManager.initHeroBaseInfo()
    for k, v in pairs(heroCfg) do
        local heroData = {};
        this.copyHeroConfig(v, heroData);
        table.insert(tabAllHero, heroData);
    end
end

--拷贝表中数据
function HeroManager.copyHeroConfig(heroCfg, heroData)
    heroData["partnerId"] = 0;
    heroData["partnerModelId"] = tostring(heroCfg.f_HeroID);
    heroData["name"] = getLanguage(heroCfg.f_HeroName);
    heroData["category"] = heroCfg.f_Type;
    heroData["type"] = heroCfg.f_HeroType;
    heroData["typeCn"] = heroCfg.f_HeroTypeCn;
    heroData["element"] = heroCfg.f_HeroElement;
    heroData["quality"] = this.starToQuality(heroCfg.f_HeroInitialStar);
    heroData["icon"] = heroCfg.f_HeroIcon;
    heroData["halfIcon"] = this.GetHeroBIcon(heroCfg.f_HeroID)
    heroData["draw"] = this.GetHeroDrawingPath(heroCfg.f_HeroID)
    heroData["cv"] = getLanguage(heroCfg.f_HeroCV);
    if heroData["skinId"] then
        heroData["model"] = heroCfg.f_HeroModel .. "-" .. heroData["skinId"];
    else
        heroData["model"] = heroCfg.f_HeroModel;
    end
    heroData["level"] = 0;
    heroData["storeId"] = heroCfg.f_StoneId;
    heroData["star"] = heroCfg.f_HeroInitialStar;
    heroData["subName"] = getLanguage(heroCfg.f_HeroSubName);
    heroData["pos"] = heroCfg.f_HeroPos
    heroData["baseAttr"] = heroCfg.f_CharacterValue;
    heroData["race"] = heroCfg.f_HeroRace;
    heroData["faction"] = heroCfg.f_FactionType;
    heroData["version"] = heroCfg.f_Version
    heroData["power"] = 0;
    heroData["realPower"] = 0;
    heroData["exp"] = 0;
    heroData["attribute"] = {};
    heroData["allAttribute"] = {};
    heroData["totalAttribute"] = {};
    heroData["equip"] = {};
    heroData["skillIds"] = {};
    heroData["state"] = 0;
    local resize, location = this.GetHeroLocationResize(heroCfg.f_HeroID)
    heroData["scale"] = resize;
    heroData["location"] = location
    heroData["collocationHero"] = decodeJsonStrToTabel(heroCfg.f_RecommendedCollocation);
    heroData["collocationDescribe"] = decodeJsonStrToTabel(heroCfg.f_CollocationDescribe);
    local heroCfg = dataTable.getRow("t_hero", heroData["partnerModelId"])
    local tempIcon = ""
    if heroCfg then
        tempIcon = heroCfg["f_HeroChibi"] or ""
    end
    heroData["smallIcon"] = tempIcon--缩略图(小的立绘图，羁绊)
end

-- 判断英雄是否解锁图鉴
function HeroManager.isOpenHeroAtlas(modelId)
    if heroLimitCfg == nil then
        return true;
    end
    local cfg = heroLimitCfg[tostring(modelId)];
    if cfg == nil then
        return true;
    end
    if not this.isHeroOpenDay(cfg.f_Open1) then
        return false;
    end
    return true;
end

-- 判断英雄是否完全放开
function HeroManager.isHeroFullyOpen(modelId)
    if heroLimitCfg == nil then
        return true;
    end
    local cfg = heroLimitCfg[tostring(modelId)];
    if cfg == nil then
        return true;
    end
    local isOpen = true;
    if cfg.f_Open3 ~= nil and tonumber(tostring(cfg.f_Open3)) > HelperFunc.GetServerTime() then
        isOpen = false;
    end
    if (not this.isHeroOpenDay(cfg.f_Open2)) and (not isOpen) then
        return false;
    end
    return true;
end

function HeroManager.isHeroOpenDay(limitOpenTime)
    if limitOpenTime ~= nil and tonumber(limitOpenTime) ~= 0 then
        local ot = tonumber(tostring((logicMgr.LoginManager.GetServerOpenTime() / 1000)))
        local t = tonumber(os.date("%H", ot))
        local updateTime = G.dataTable["t_global"][tostring(35)].f_int_value;
        local openTime = 0
        if t * 3600 >= updateTime then
            openTime = logicMgr.ActiveManager.getDataUpateTime(ot) + tonumber(limitOpenTime) * 3600 * 24 - HelperFunc.GetServerTime();
        else
            openTime = logicMgr.ActiveManager.getDataUpateTime(ot + 3600 * 24) + tonumber(limitOpenTime) * 3600 * 24 - HelperFunc.GetServerTime();
        end
        if openTime > 0 then
            return false;
        end
    end
    return true;
end

--拷贝表中数据
function HeroManager.copyHeroConfigbyModelId(modelId, heroData)
    local cfg = heroCfg[tostring(modelId)];
    this.copyHeroConfig(cfg, heroData);
end

function HeroManager.GetHeroConfigbyModelId(modelId)
    local cfg = heroCfg[tostring(modelId)];
    return cfg;
end
function HeroManager.GetHeroIconByModelId(modelId, skinId)
    local cfg = heroCfg[tostring(modelId)];
    if not cfg then
        return ""
    end
    local path = cfg.f_HeroIcon
    if skinId and tonumber(skinId) > 0 then
        skinId = tonumber(skinId)
        local isOrignalSkin = G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0   --是否原皮
        if not isOrignalSkin then
            path = dataTable.getDataTableByStringId("t_skin", skinId, "f_HeroIcon")
        end
    end
    return path
end
function HeroManager.GetHeroQualityByModelId(modelId)
    local cfg = heroCfg[tostring(modelId)];
    if cfg then
        return this.starToQuality(cfg.f_HeroInitialStar);
    end
    return 1
end
function HeroManager.GetHeroStarByModelId(modelId)
    local cfg = heroCfg[tostring(modelId)];
    if cfg then
        return cfg.f_HeroInitialStar;
    end
    return 10
end
function HeroManager.GetHeroNameByModelId(modelId)
    local heroModelId = tostring(modelId);
    for k, v in pairs(tabAllHero) do
        if v.partnerModelId == heroModelId then
            return v.name
        end
    end
    return "can't find hero id:" .. modelId;
end

function HeroManager.GetHeroSubnameByModelId(modelId)
    local heroModelId = tostring(modelId);
    for k, v in pairs(tabAllHero) do
        if v.partnerModelId == heroModelId then
            return v.subName
        end
    end
    return "can't find hero id:" .. modelId;
end

function HeroManager.GetHeroStoneIdByModelId(modelId)
    local heroData = heroCfg[tostring(modelId)];
    if heroData then
        return heroData.f_StoneId;
    end
    return modelId;
end
function HeroManager.getHeroInteractionNum()
    return this.heroInteractionNum
end

function HeroManager.updateInteractionNum(notFire)
    local _, info = logicMgr.HeroFavorManager.getInteractionInfo()
    local shareNum = 0
    if #tabOwner == 0 then
        tabOwner = HeroManager.getOwnerHeroList(false, nil, true);
    end
    for i = 1, #tabOwner do
        local lastGetTime = tabOwner[i].lastInteractTime or 0
        local interactData = tabOwner[i]["interactInfos"] or {}
        local now = HelperFunc.GetServerTime()
        local dis = GetTimeStampDayDis(lastGetTime / 1000, now)
        if dis <= 0 then
            for a, b in ipairs(interactData) do
                if info[tostring(b.id)].f_FrequencyType == 1 then
                    shareNum = shareNum + b.times
                end
            end
        end
    end
    if not notFire then
        FireEvent(Config.EventType.Fresh_HeroInteraction)
    end
    this.heroInteractionNum = shareNum
end

--通过modelId获取英雄数据
function HeroManager.getHeroDatabyModelId(modelId, ignoreClone)
    if modelId == nil then
        return nil
    end
    local heroModelId = tostring(modelId);
    for i = 1, #tabAllHero do
        if tabAllHero[i]["partnerModelId"] == heroModelId then
            logicMgr.HeroManager.setHeroInteraction({ partnerId = tabAllHero[i].partnerId or 0 })
            if not ignoreClone then
                return clone(tabAllHero[i]);
            else
                return tabAllHero[i]
            end
        end
    end
    return nil;
end

--通过partnerId获取英雄数据
function HeroManager.getHeroDatabyPartnerId(partnerId, ignoreClone)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        if allHeroPetAttrDirty[heroPartnerId] == nil or allHeroPetAttrDirty[heroPartnerId] then
            allHeroPetAttrDirty[heroPartnerId] = false
            --this.processHeroPetAttr(tabKeyMap[heroPartnerId])
            this.processHeroAllAttr(tabKeyMap[heroPartnerId])
        end
        logicMgr.HeroManager.setHeroInteraction({ partnerId = heroPartnerId or 0 })

        if not ignoreClone then
            return clone(tabKeyMap[heroPartnerId]);
        else
            return tabKeyMap[heroPartnerId]
        end
    end
    return nil;
end

--星转品质
function HeroManager.starToQuality(star)
    if star == nil then
        return 0;
    end
    return Mathf.Floor(star / 10);
end

function HeroManager.getNextStar(star)
    return Mathf.Floor(star / 10) * 10 + 10
end

function HeroManager.getLastStar(star)
    return Mathf.Floor(star / 10) * 10 - 10
end

function HeroManager.getLastQuality(star)
    return this.starToQuality(this.getLastStar(star))
end

function HeroManager.getNextQuality(star)
    return this.starToQuality(this.getNextStar(star))
end

function HeroManager.starToShow(star)
    star = tonumber(star);
    if (star > HeroManager.LimitStar()) then
        star = HeroManager.LimitStar();
    end
    return star;
end

function HeroManager.LimitStar()
    if (limitStarNum == 0) then
        limitStarNum = HelperFunc.GetGlobalNumVlue(93)
    end
    return limitStarNum;
end

--通过modelId设置partnerId
function HeroManager.setHeroPartnerId(modelId, partnerId, isNew)
    local heroPartnerId = tostring(partnerId);
    local heroModelId = tostring(modelId);
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        if hero["partnerModelId"] == heroModelId then
            hero["partnerId"] = heroPartnerId;
            if isNew then
                --新获得的英雄
                if this.getNewHeroShow then
                    if this.needShowHeroList == nil or #this.needShowHeroList == 0 then
                        this.needShowHeroList = {};
                    end
                    table.insert(this.needShowHeroList, { hero["partnerModelId"], nil, hero["partnerId"] });
                else
                    hero.isNew = true;
                end
            end
            hero.active = nil
            tabKeyMap[heroPartnerId] = hero;
            break ;
        end
    end
end

function HeroManager.getAllRankHero()
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i]
        if tonumber(hero["category"]) == 0 and hero["version"] == 1 and this.isOpenHeroAtlas(hero["partnerModelId"]) then
            if toNumber(tabAllHero[i]["partnerId"]) == 0 then
                hero["partnerId"] = toNumber(hero["partnerModelId"])
            end
            table.insert(list, hero);
        end
    end
    return list;
end
function HeroManager.AllRestRankHero()
    for i = 1, #tabAllHero do
        if toNumber(tabAllHero[i]["partnerId"]) < 10000 then
            tabAllHero[i]["partnerId"] = 0
        end
    end
end
function HeroManager.RankBattleSetState(partnerModelId, state)
    for i = 1, #tabAllHero do
        if tabAllHero[i].partnerModelId == partnerModelId then
            tabAllHero[i].state = state
        end
    end
end
--英雄是否拥有
function HeroManager.NotHaveByModeId(modelId)
    local list = HeroManager.getUnOwnerHeroList()
    for _, v in pairs(list) do
        if tonumber(modelId) == tonumber(v.partnerModelId) then
            return true
        end
    end
    return nil
end
function HeroManager.IsHaveByPartnerModelId(partnerId)
    local list = HeroManager.getOwnerHeroListReadOnly()
    for _, v in pairs(list) do
        if tonumber(partnerId) == tonumber(v.partnerModelId) then
            return true
        end
    end
    return false
end
function HeroManager.IsHaveByItemModelId(itemModelId)
    local constData = ItemManager.getItemConstDatabyModelId(itemModelId)
    return HeroManager.IsHaveByPartnerModelId(constData.partnerModelId)
end
function HeroManager.GetRandomOwnerHeroModelId()
    local list = this.getOwnerHeroListReadOnly()
    local count = #list
    if count == 0 then
        return -1
    end
    local r = math.random(1, count + 1)
    if r > count then
        r = count
    end
    local hero = list[r]
    return tonumber(hero.partnerModelId)
end
--获取拥有英雄列表
function HeroManager.getOwnerHeroListNoClone(type)
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        local parnterId = hero["partnerId"]
        if tonumber(parnterId) > 10000 then
            if type and type ~= 0 and hero.version ~= 2 then
                if hero.type == type then
                    table.insert(list, hero)
                end
            else
                table.insert(list, hero)
            end
        end
    end
    return list;
end
--获取拥有英雄列表
function HeroManager.getOwnerHeroList(aa, type, ignoreClone)
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        local parnterId = hero["partnerId"]
        if tonumber(parnterId) > 10000 and hero.version ~= 2 then
            if type and type ~= 0 then
                if hero.type == type then
                    if ignoreClone then
                        table.insert(list, hero)
                    else
                        table.insert(list, clone(hero))
                    end
                end
            else
                if ignoreClone then
                    table.insert(list, hero)
                else
                    table.insert(list, clone(hero))
                end
            end
        end
    end
    this.SetMyHeroSkin(list)
    return list;
end
--获取拥有英雄列表,只读数据，不要改变数据，因为getOwnerHeroList调用太多，选择少数能确定的另加接口
function HeroManager.getOwnerHeroListReadOnly(type)
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        local parnterId = hero["partnerId"]
        if tonumber(parnterId) > 10000 then
            if type and type ~= 0 and hero.version ~= 2 then
                if hero.type == type then
                    table.insert(list, hero)
                end
            else
                table.insert(list, hero)
            end
        end
    end
    return list;
end

--
function HeroManager.getOwnerHeroListLevelUp(aa, type, level, needClone)
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        local parnterId = hero["partnerId"]
        if tonumber(parnterId) > 10000 then
            if type and type ~= 0 then
                if hero.type == type then
                    local is_inlink = logicMgr.HeroLinkManager.isInLink(parnterId, false)
                    if level and not is_inlink then
                        if hero.level > level then
                            if needClone then
                                table.insert(list, clone(hero))
                            else
                                table.insert(list, hero)
                            end
                        end
                    else
                        if needClone then
                            table.insert(list, clone(hero))
                        else
                            table.insert(list, hero)
                        end
                    end
                end
            else
                local is_inlink = logicMgr.HeroLinkManager.isInLink(parnterId, false)
                if level and not is_inlink then
                    if hero.level > level then
                        if needClone then
                            table.insert(list, clone(hero))
                        else
                            table.insert(list, hero)
                        end
                    end
                else
                    if needClone then
                        table.insert(list, clone(hero))
                    else
                        table.insert(list, hero)
                    end
                end
            end
        end
    end
    return list;
end

function HeroManager.SetAllPower(partnerId, isBefore, isAfter)
    if partnerId and tostring(partnerId) ~= "0" then
        local heroInfo = HeroManager.getHeroDatabyPartnerId(tostring(partnerId), true);
        if heroInfo ~= nil then
            if isBefore then
                beforePower = heroInfo["power"]
            end
            if isAfter then
                afterPower = heroInfo["power"]
            end
        else
            logError("Error partner:" .. partnerId);
        end
    else
        return beforePower, afterPower
    end

end

function HeroManager.GetTopHerosPower()
    local list = this.getOwnerHeroListReadOnly()
    local sumPower = 0
    local num = 6;
    if #list < num then
        num = #list;
    end
    table.sort(list, function(a, b)
        return a["power"] > b["power"];
    end);
    for i = 1, num do
        sumPower = sumPower + list[i]["power"]
    end
    return tonumber(tostring(sumPower))
end
--- 获取出生英雄列表的表格ID
function HeroManager.GetBornHeroCfgTbale()
    local cfgInfo = HelperFunc.GetGlobalVlue(5)
    local initHeroCfg = nil
    if cfgInfo and not initHeroCfg then
        initHeroCfg = {}
        for _, v in pairs(cfgInfo) do
            initHeroCfg[v] = v
        end
    end
    return initHeroCfg
end

--- 获取拥有列表中的初始英雄列表
function HeroManager.GetHeroListForBorn()
    local initHeroCfg = HeroManager.GetBornHeroCfgTbale()
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        local parnterId = hero["partnerId"]
        local cfgID = toNumber(hero["partnerModelId"])
        if tonumber(parnterId) > 10000 and initHeroCfg and initHeroCfg[cfgID] then
            table.insert(list, hero)
        end
    end
    return list;
end

--获取未拥有英雄列,,,确认是只读的再传needClone
function HeroManager.getUnOwnerHeroList(needClone)
    local list = {};
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        if tonumber(hero["partnerId"]) < 10000 and hero.version ~= 2 and this.isOpenHeroAtlas(hero["partnerModelId"]) then
            if needClone then
                table.insert(list, clone(hero));
            else
                table.insert(list, hero)
            end

        end
    end
    return list;
end
function HeroManager.HasOwnHeroByModelId(modelId)
    for k, v in pairs(tabKeyMap) do
        if tonumber(v.partnerModelId) == tonumber(modelId) then
            return true
        end
    end
    return false
end
--设置级别
function HeroManager.setHeroLevel(partnerId, level)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["level"] = level;
    end
end
function HeroManager.GetHeroLevel(partnerId)
    return tabKeyMap[tostring(partnerId)]["level"] or 0
end

function HeroManager.GetHeroType(partnerId)
    return tabKeyMap[tostring(partnerId)]["type"] or 0
end

function HeroManager.GetHeroModelId(partnerId)
    return tabKeyMap[tostring(partnerId)]["partnerModelId"] or 0
end

function HeroManager.GetHeroAdd()
    return heroAdds;
end

function HeroManager.RefreshHeroAdd()
    heroAdds = { 0, 0, 0, 0, 0, 0 };
    local cfg = G.dataTable["t_professionaddition"];
    for k, v in pairs(tabKeyMap) do
        if tabKeyMap[k].star >= cfg[tostring(tabKeyMap[k].type)].f_NeedRank then
            heroAdds[tabKeyMap[k].type] = heroAdds[tabKeyMap[k].type] + 1;
        end
    end
    for k, v in pairs(heroAdds) do
        if v >= 3 then
            heroAdds[k] = 3;
        end
    end
end

--设置名字
function HeroManager.setHeroName(partnerId, name)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["name"] = name;
    end
end

--设置星级
function HeroManager.setHeroStar(partnerId, star)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["star"] = star;
        tabKeyMap[heroPartnerId]["quality"] = HeroManager.starToQuality(star);
    end
end
function HeroManager.GetHeroQuality(partnerId)
    local heroPartnerId = tostring(partnerId)
    if tabKeyMap[heroPartnerId] ~= nil then
        return tabKeyMap[heroPartnerId]["quality"];
    end
    return 0
end
function HeroManager.GetHeroStar(partnerId)
    local heroPartnerId = tostring(partnerId)
    if tabKeyMap[heroPartnerId] ~= nil then
        return tabKeyMap[heroPartnerId]["star"]
    end
    return 0
end

function HeroManager.GetHeroStarByPartnerModelId(partnerModelId)
    local heroPartnerId = tonumber(partnerModelId)
    for k, v in pairs(tabKeyMap) do
        if tonumber(v.partnerModelId) == heroPartnerId then
            return v.star or 0
        end
    end
    return 0
end

--设置经验
function HeroManager.setHeroExp(partnerId, exp)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["exp"] = exp;
    end
end

--设置新英雄标签
function HeroManager.setHeroIsNew(partnerId, is, heroSource)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        if tabKeyMap[heroPartnerId]["isNew"] then
            local _partnerModelId = tostring(tabKeyMap[heroPartnerId]["partnerModelId"])
            HeroManager.SetNewHeroTA(_partnerModelId, heroSource)
        end
        tabKeyMap[heroPartnerId]["isNew"] = is;
    end
end

--- 初始化已激活的羁绊id(随着英雄重生 羁绊也跟随清空)
function HeroManager.setHeroFetter(partnerId, feltterList)
    local heroPartnerId = tostring(partnerId)
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["fetter"] = {}
        for _, id in pairs(feltterList) do
            tabKeyMap[heroPartnerId]["fetter"][id] = id
        end
    end
end
--
function HeroManager.GetHeroPower(partnerId)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        return tabKeyMap[heroPartnerId]["power"]
    end
end
--zhanli
function HeroManager.setHeroPower(partnerId, power, isAdd)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        if not isAdd then
            tabKeyMap[heroPartnerId]["power"] = tonumber(tostring(power));
        else
            tabKeyMap[heroPartnerId]["power"] = (tabKeyMap[heroPartnerId]["power"] or 0) + tonumber(tostring(power));
        end
    end
end
--战力，不包含智慧之链提升的
function HeroManager.setHeroRealPower(partnerId, power, isAdd)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        if not isAdd then
            tabKeyMap[heroPartnerId]["realPower"] = tonumber(tostring(power))
        else
            tabKeyMap[heroPartnerId]["realPower"] = (tabKeyMap[heroPartnerId]["realPower"] or 0) + tonumber(tostring(power));
        end
    end
end
function HeroManager.setHeroInteraction(partnerData)
    partnerData = partnerData or {}
    local heroPartnerId = tostring(partnerData.partnerId or 0)
    if tabKeyMap[heroPartnerId] ~= nil then
        if partnerData.favorLv ~= nil or tabKeyMap[heroPartnerId].favorLv == nil then
            tabKeyMap[heroPartnerId]["favorLv"] = partnerData.favorLv or 0
            tabKeyMap[heroPartnerId]["favorExp"] = partnerData.favorExp or 0
            local lastInteractTime = ConvertCSharpLongNumber(partnerData.lastInteractTime) or 0
            tabKeyMap[heroPartnerId]["lastInteractTime"] = lastInteractTime
            tabKeyMap[heroPartnerId]["favorRewardGetLv"] = partnerData.favorRewardGetLv or 0
            tabKeyMap[heroPartnerId]["interactInfos"] = partnerData.interactInfos or {}

            local now = HelperFunc.GetServerTime()
            local dis = GetTimeStampDayDis(tabKeyMap[heroPartnerId]["lastInteractTime"] / 1000, now)
            if dis > 0 then
                for i, v in ipairs(tabKeyMap[heroPartnerId]["interactInfos"]) do
                    v.times = 0
                end
            end
        end
    end
end
function HeroManager.GetHeroPower(partnerId)
    return tabKeyMap[tostring(partnerId)]["power"] or 0
end
--- 更新英雄的sameNum属性
-- isAdd 是否进行追加
function HeroManager.setHeroSameNum(partnerId, sameNum, isAdd)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] ~= nil then
        if not isAdd then
            tabKeyMap[heroPartnerId]["sameNum"] = sameNum;
        else
            tabKeyMap[heroPartnerId]["sameNum"] = (tabKeyMap[heroPartnerId]["sameNum"] or 0) + sameNum;
        end
    end
end
function HeroManager.GetHeroSameNum(partnerId)
    return tabKeyMap[tostring(partnerId)]["sameNum"] or 0
end

--- 计算羁绊属性加成
function HeroManager.CalculateAllFitterAttr()
    fetterAttrList = {}
    fetterPower = 0
    for _, heroInfo in pairs(tabAllHero) do
        if heroInfo["fetter"] then
            for _, fetterID in pairs(heroInfo["fetter"]) do
                local cfgInfo = G.dataTable["t_trammel"][tostring(fetterID)]
                if cfgInfo then
                    fetterPower = fetterPower + cfgInfo.f_PowerBase;
                    local attrList = decodeJsonStrToTabel(cfgInfo["f_AttributeBonus"])
                    if attrList then
                        for _, v in pairs(attrList) do
                            local attrId = v[1]
                            local attrNum = v[2]

                            if fetterAttrList[attrId] == nil then
                                fetterAttrList[attrId] = attrNum
                            else
                                fetterAttrList[attrId] = fetterAttrList[attrId] + attrNum
                            end
                        end
                    end
                end
            end
        end
    end
    for _, heroInfo in pairs(tabAllHero) do
        heroInfo.allAttribute[EnumConst.AttributeTypeEnum.Fellter] = fetterAttrList;
        this.processHeroAllAttr(heroInfo);
    end
end

--- 初始化已激活的羁绊id(英雄重生 羁绊不清空)
function HeroManager.SetForverHeroFetter(feltterList)
    tabFetter = {}
    for _, id in pairs(feltterList) do
        tabFetter[id] = id
    end
end

--- 获取已激活的羁绊table
function HeroManager.GetForverHeroFetter(feltterID)
    if feltterID then
        return tabFetter[feltterID]
    end
    return tabFetter
end
--根据modelId获取该英雄的所有羁绊
function HeroManager.GetFetterInfoByModelId(id)
    return fetterGroup[id];
end

--- 计算羁绊奖励点
function HeroManager.GetHeroFetterAwardValue()
    local acount = 0
    local fetterTable = logicMgr.HeroManager.GetForverHeroFetter()
    for _, fetterID in pairs(fetterTable) do
        local cfgInfo = G.dataTable["t_trammel"][tostring(fetterID)]
        if cfgInfo then
            acount = acount + cfgInfo["f_TrammelPoint"] or 0
        end
    end

    if CurrentTrammelPoint ~= acount then
        local _currentId = 0
        local _reawrdConfig = G.dataTable["t_trammelpointreward"]
        for index, value in ipairs(_reawrdConfig) do
            if value.f_Point < acount then
                _currentId = index
            else
                break
            end
        end

        local _trammelDic = {}
        _trammelDic.trammelpoint_id = tonumber(_currentId)
        _trammelDic.delta_trammelpoint = tonumber(acount - CurrentTrammelPoint)
        _trammelDic.current_trammelpoint = tonumber(acount)
        TAManager.TrackByDictionary("trammel_progress", _trammelDic)
        CurrentTrammelPoint = acount
    end
    return acount
end

--- 获取羁绊奖励领取列表
function HeroManager.GetHeroFetterHadAwardList()
    return fetterHadAwardTable or {};
end

--- 获取羁绊奖励领取列表
function HeroManager.AddHeroFetterHadAwardList(addAwardID)
    if addAwardID and not fetterHadAwardTable[addAwardID] then
        fetterHadAwardTable[addAwardID] = addAwardID
    end
end

--- 设置羁绊奖励领取列表
function HeroManager.SetHeroFetterHadAwardList(idList)
    if idList ~= nil then
        fetterHadAwardTable = {};

        for index, key in pairs(idList) do
            fetterHadAwardTable[key] = key

        end
    end
end
--- 修改指定羁绊数据
function HeroManager.ChangeForverHeroFetter(feltterID, isDel)
    if isDel then
        if tabFetter[feltterID] then
            tabFetter[feltterID] = nil
        end
    else
        if not tabFetter[feltterID] then
            tabFetter[feltterID] = feltterID
        end
    end
end

--- 羁绊激活追加id
function HeroManager.appendHeroFetter(partnerId, feltterID)
    local heroPartnerId = tostring(partnerId)
    if tabKeyMap[heroPartnerId] ~= nil then
        if tabKeyMap[heroPartnerId]["fetter"] == nil then
            tabKeyMap[heroPartnerId]["fetter"] = {}
        end

        if not tabKeyMap[heroPartnerId]["fetter"][feltterID] then
            tabKeyMap[heroPartnerId]["fetter"][feltterID] = feltterID
        end
    end
end

--- 清除指定英雄的羁绊信息(重生调用)
function HeroManager.ClearHeroFetter(partnerId)
    local heroPartnerId = tostring(partnerId)
    if tabKeyMap[heroPartnerId] ~= nil then
        tabKeyMap[heroPartnerId]["fetter"] = {}
    end
end

--设置状态
function HeroManager.setHeroState(partnerId, value, stateEnum, fightType, data)
    local heroPartnerId = tostring(partnerId);
    if tabKeyMap[heroPartnerId] and tabKeyMap[heroPartnerId]["state"] and stateEnum then
        if not value and ZZMathBit.andOp(tabKeyMap[heroPartnerId]["state"], stateEnum) > 0 then
            tabKeyMap[heroPartnerId]["state"] = ZZMathBit.xorOp(tabKeyMap[heroPartnerId]["state"], stateEnum);
        elseif value and ZZMathBit.andOp(tabKeyMap[heroPartnerId]["state"], stateEnum) == 0 then
            tabKeyMap[heroPartnerId]["state"] = ZZMathBit.orOp(tabKeyMap[heroPartnerId]["state"], stateEnum);
        end
        return tabKeyMap[heroPartnerId];
    else
        if fightType == EnumConst.FightTypeConst.RankBattle or fightType == EnumConst.FightTypeConst.DUNGEON then
            if not value and ZZMathBit.andOp(data["state"], stateEnum) > 0 then
                data["state"] = ZZMathBit.xorOp(data["state"], stateEnum);
            elseif value and ZZMathBit.andOp(data["state"], stateEnum) == 0 then
                data["state"] = ZZMathBit.orOp(data["state"], stateEnum);
            end
            if fightType == EnumConst.FightTypeConst.RankBattle then
                this.RankBattleSetState(data["partnerModelId"], data["state"]);
            end
            return data
        end
    end
    return nil;
end

--重生
function HeroManager.resetHero(partnerId)
    local heroData = tabKeyMap[partnerId];
    if heroData ~= nil then
        local _lastLv = heroData.level
        heroData.level = 1;
        --heroData.star = heroCfg[heroData.partnerModelId].f_HeroInitialStar;
        heroData.equip = {};
        this.updateHeroBaseAttr(partnerId, true, nil, nil, nil, true);

        --英雄重生 TA
        local _heroDic = {}
        _heroDic.hero_uniqueid = tostring(partnerId)
        _heroDic.hero_id = tostring(heroData["partnerModelId"])
        _heroDic.old_hero_level = tonumber(_lastLv)
        TAManager.TrackByDictionary("hero_rebirth", _heroDic)
    end

    --this.ClearHeroFetter(partnerId) --清除对应羁绊信息
end

--初始化图鉴
function HeroManager.initHandbook(table)
    tableHandbook = {};
    for i = 1, #table do
        local data = {};
        data.partnerModelId = table[i].partnerModelId;
        data.isReward = table[i].draw > 0;
        data.share = table[i].share
        tableHandbook[tostring(data.partnerModelId)] = data;
    end
end

--添加图鉴信息
function HeroManager.setHandbook(model, isReward)
    if tableHandbook[model] then
        tableHandbook[model].isReward = true
    else
        tableHandbook[model] = { partnerModelId = model, isReward = isReward, share = 0 };
    end
end

-- 获取英雄图鉴信息 nil代表未激活(modelId 要求必须是string类型，调用者必须明确，现在函数内部做统一处理，后期视情况进行优化)
function HeroManager.getHandbookByModelId(modelId, isClone)
    modelId = tostring(modelId)
    if tableHandbook[modelId] ~= nil then
        if not isClone then
            return clone(tableHandbook[modelId]);
        else
            return tableHandbook[modelId]
        end
    end
    return nil
end

-- 获取英雄图鉴全部信息
function HeroManager.getHandbooks()
    return clone(tableHandbook);
end

--设置水晶信息
function HeroManager.setCrystalInfo(msg)
    crystalInfo.level = msg.crystalLevel;
    crystalInfo.exp = msg.crystalValue;
end

--获取水晶信息
function HeroManager.getCrystalInfo()
    return crystalInfo;
end

--设置结算时间
function HeroManager.setSettleTime(time)
    settleTime = time
end
--获取结算时间
function HeroManager.getSettleTime()
    return settleTime == nil and 0 or settleTime;
end
--获取挂机最大时间
function HeroManager.getSettleingMaxTime()
    return dataTable.getGlobalInt(95) + logicMgr.EcoBuffManager.getEcoBuffByTypeAndItemId(Config.EcoBuffCondition.OffLineTime)
end

--设置快速战斗次数
function HeroManager.setQuickTimes(times)
    quickTimes = times;
end
--获取快速战斗次数
function HeroManager.getQuickTimes()
    return quickTimes == nil and 0 or quickTimes;
end

function HeroManager.CalcHeroPowerWithLv(partnerId, level)
    this.CalculateAllFitterAttr()
    local herodata = clone(tabKeyMap[partnerId])
    herodata.level = 300
    this.processHeroBaseAttr(herodata,300,tabKeyMap[partnerId]["star"])
    this.processHeroEquipAttr(herodata);
    this.processHeroWeaponAttr(herodata);
    this.processWeaponSkin(herodata)
    this.processHeroAllAttr(herodata);
    return this.CalcHeroPowerByAttrs(partnerId,herodata)
end
--增量刷新属性
function HeroManager.UpdateAddAttr(attrs)
    local heroList = this.getOwnerHeroListReadOnly()
    for _,v in pairs(heroList) do
        for i,value in pairs(attrs) do
            local temp
            if i ==1 or i ==2 or i ==3 then
                temp = math.floor((value or 0)*(1+v["totalAttribute"][i+13] / 10000))
            else
                temp = value
            end
            if v["totalAttribute"][i] then
                v["totalAttribute"][i] = v["totalAttribute"][i] + temp
            else
                v["totalAttribute"][i] = temp
            end
        end
    end
end

function HeroManager.CalcHeroPower(partnerId, real,isOld)
    if isOld then
        return tabKeyMap[tostring(partnerId)].power
    end
    return this.CalcHeroPowerByAttrs(partnerId)
end
--潜能更新属性
function HeroManager.UpdatePotentialAttr(heroPartnerId,type, overrideLevel)
    if type then
        if type ==1 then
            this.processHeroBaseAttr(tabKeyMap[heroPartnerId],this.getHeroShowLevelByPartnerId(heroPartnerId),tabKeyMap[heroPartnerId]["star"], overrideLevel)
        end
        if type == 2 then
            this.processHeroEquipAttr(tabKeyMap[heroPartnerId]);
        end
        if type == 3 then
            this.processHeroWeaponAttr(tabKeyMap[heroPartnerId]);
        end
    else
        this.processHeroBaseAttr(tabKeyMap[heroPartnerId],this.getHeroShowLevelByPartnerId(heroPartnerId),tabKeyMap[heroPartnerId]["star"], overrideLevel)
        this.processHeroEquipAttr(tabKeyMap[heroPartnerId]);
        this.processHeroWeaponAttr(tabKeyMap[heroPartnerId]);
        this.processWeaponSkin(tabKeyMap[heroPartnerId])
        this.CalculateAllFitterAttr()
    end
    this.processHeroAllAttr(tabKeyMap[heroPartnerId]);
end
--更新属性
function this.UpdateAllAttr()
    local heroList = this.getOwnerHeroListReadOnly()
    for _,v in pairs(heroList) do
        this.processHeroAllAttr(v);
    end
end
--更新属性
function HeroManager.UpdateAllBaseAttr()
    local heroList = this.getOwnerHeroListReadOnly()
    for _,v in pairs(heroList) do
        this.updateHeroBaseAttr(v.partnerId);
    end
end
--- showFont:是否显示属性跳字
function HeroManager.updateHeroBaseAttr(partnerId, showFont, islevel, isFetter, notUpdatePower, isAll, noSetBefore)
    local heroPartnerId = tostring(partnerId);
    attrTable = {}
    local atkValue, defValue, hpValue = HeroManager.GetAttFont(partnerId)
    attrTable[2] = atkValue or 0
    attrTable[4] = defValue or 0
    attrTable[6] = hpValue or 0
    attrTable[7] = (showFont) or isAll
    if not StrangeFragmentManager.isChange and not noSetBefore then
        HeroManager.SetAllPower(heroPartnerId, true)
    end
    if tabKeyMap[heroPartnerId] ~= nil then
        local level = this.getHeroShowLevelByPartnerId(heroPartnerId);
        this.processHeroBaseAttr(tabKeyMap[heroPartnerId], level, tabKeyMap[heroPartnerId]["star"], true);
        if not islevel then
            this.processHeroEquipAttr(tabKeyMap[heroPartnerId]);
            this.processHeroWeaponAttr(tabKeyMap[heroPartnerId]);
            this.processWeaponSkin(tabKeyMap[heroPartnerId])
            --this.processHeroPetAttr(tabKeyMap[heroPartnerId]);
            this.CalculateAllFitterAttr()
        end
        this.processHeroAllAttr(tabKeyMap[heroPartnerId], islevel);
        if not notUpdatePower then
            partnerHandler.ReqHeroPower(tostring(partnerId), attrTable[7])
        end
    end
    local _atkValue, _defValue, _hpValue = HeroManager.GetAttFont(partnerId)
    attrTable[1] = _atkValue or 0
    attrTable[3] = _defValue or 0
    attrTable[5] = _hpValue or 0
    attrTable[8] = isAll
    if attrTable[7] and beforePower == afterPower then
        attrTable = {}
        return
    end
    HeroManager.ShowFont()
end
function HeroManager.ShowFont()
    if attrTable[7] then
        HeroManager.UpTipsAtt(attrTable[1], attrTable[2], attrTable[3], attrTable[4], attrTable[5], attrTable[6], nil, attrTable[8])
        attrTable = {}
    end
end

function HeroManager.CalcBeforePower()
    beforePower = this.GetHerosSumPower()
end

function HeroManager.ShowAllPower()
    partnerHandler.ReqHeroPower(0)
    afterPower = this.GetHerosSumPower()

    logicMgr.HeroManager.UpTipsAtt(0, 0, 0, 0, 0, 0, nil, true)
end
--[[属性飘字
    _atkValue 第一条添加值
    atkValues 第一条基础值
    _defValue 第二条添加值
    defValue  第二条基础值
    _hpValue  第三条添加值
    hpValue   第三条基础值
]]
function HeroManager.UpTipsAtt(_atkValue, atkValue, _defValue, defValue, _hpValue, hpValue, isFetter, isAll, befornum, Afternum)
    if isAll then
        if not befornum then
            befornum, Afternum = logicMgr.HeroManager.SetAllPower()
        end
        if Mathf.Round(math.abs(Afternum - befornum)) == 0 then
            return ;
        end
    end
    local str = Mathf.Round(_atkValue) .. "," .. Mathf.Round(atkValue) .. "," ..Mathf.Round( _defValue) .. "," .. Mathf.Round(defValue) .. "," .. Mathf.Round(_hpValue) .. "," .. Mathf.Round(hpValue);
    local name, packname = getUIName(PanelNames.UICommonHeroUp)
    if upPoolNum >= 8 then
        -- ???
        obj = upPool1;
        --table.remove(upPool, 1)
    else
        obj = newGComponent(name, packname);
    end
    local ctrl = CtrlManager.GetCtrl(PanelNames.UICommonHeroUp)
    obj.visible = true
    GRoot.inst:AddChild(obj);
    obj.x = Config.uiXOffset
    --table.insert(upPool, obj);
    if upPoolNum == 0 then
        upPoolNum = 1
        upPool1 = obj
    elseif upPoolNum == 1 then
        upPoolNum = 2
        upPool2 = obj
    elseif upPoolNum == 2 then
        upPoolNum = 3
        upPool3 = obj
    elseif upPoolNum == 3 then
        upPoolNum = 4
        upPool4 = obj
    elseif upPoolNum == 4 then
        upPoolNum = 5
        upPool5 = obj
    elseif upPoolNum == 5 then
        upPoolNum = 6
        upPool6 = obj
    elseif upPoolNum == 6 then
        upPoolNum = 7
        upPool7 = obj
    elseif upPoolNum == 7 then
        upPoolNum = 8
        upPool8 = obj
    else
        upPoolNum = 8
        upPool1 = upPool2
        upPool2 = upPool3
        upPool3 = upPool4
        upPool4 = upPool5
        upPool5 = upPool6
        upPool6 = upPool7
        upPool7 = upPool8
        upPool8 = obj
    end
    obj.sortingOrder = 1000;
    ctrl.ShowInfo(obj, str, isFetter, isAll, befornum, Afternum);
end

function HeroManager.GetAttFont(partnerId)
    local currentHeroData = HeroManager.getHeroDatabyPartnerId(partnerId, true)
    if currentHeroData then
        local attrData = currentHeroData["totalAttribute"]
        local atkValue = attrData[EnumConst.FighterAttributeEnum.ATK]
        local defValue = attrData[EnumConst.FighterAttributeEnum.DEF]
        local hpValue = attrData[EnumConst.FighterAttributeEnum.HP]
        return atkValue, defValue, hpValue
    else
        return nil
    end
end

function HeroManager.IsHeroByModelId(id)
    -- 根据ID判断角色是否属于英雄角色
    local hero = heroCfg[tostring(id)];
    return hero.f_Type == EnumConst.HeroCategory.Normal or hero.f_Type == EnumConst.HeroCategory.Leader;
end

--计算英雄基础属性
function HeroManager.processHeroBaseAttr(heroData, level, star, overrideLevel)
    --基础属性
    if star >= 150 then
        star = 150
    end
    --因为巅峰等级添加小阶段，所以重新获取等级和小阶段计算
    local phase = 0
    if overrideLevel then
        level, _, phase = this.getHeroShowLevelByPartnerId(heroData.partnerId);
    end
    local id = MakeTopLevelId(level, phase)
    local lvUpCfg = dataTable.getDataTableByStringId("t_levelupattribute",id);
    local rankUpCfg = G.dataTable["t_herorankupco"][tostring(star)];
    heroData["allAttribute"][EnumConst.AttributeTypeEnum.BASE] = {};
    if not lvUpCfg then
        --logError("can not find lvUpCfg by level:"..level)   --暂时屏蔽 影响调试
        return
    end
    if not rankUpCfg then
        logError("can not find rankUpCfg by level:" .. star)
        return
    end
    if lvUpCfg.f_Para ~= nil and rankUpCfg.f_RankUpCo ~= nil then
        local attrs = decodeJsonStrToTabel(heroData["baseAttr"]);
        for i = 1, #attrs do
            heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][attrs[i][1]] = attrs[i][2];
        end
        --升级
        local atk = heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.ATK] * lvUpCfg.f_Para / 10000
        local def = heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.DEF] * lvUpCfg.f_Para / 10000
        local hp = heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.HP] * lvUpCfg.f_Para / 10000

        --升星
        atk = atk * rankUpCfg.f_RankUpCo / 10000;
        def = def * rankUpCfg.f_RankUpCo / 10000;
        hp = hp * rankUpCfg.f_RankUpCo / 10000;
        --星级属性修正
        local cfg = dataTable.getDataTableByMultiId("t_levelupaddattribute", heroData.star, tonumber(heroData.partnerModelId))
        local total = {0,0,0}
        if cfg then
            local level = this.getHeroShowLevelByPartnerId(heroData.partnerId)
            local attr1 = decodeJsonStrToTabel(cfg.f_Attribute1)
            for k, v in pairs(attr1) do
                local attr = v[1]
                local value = v[2] * level
                total[attr] = total[attr] and (total[attr] + value) or value
            end
            local attr2 = decodeJsonStrToTabel(cfg.f_Attribute2)
            for k, v in pairs(attr2) do
                local attr = v[1]
                local value = v[2]
                total[attr] = total[attr] and (total[attr] + value) or value
            end
        end
        local tempAtk = Mathf.Round((atk ))
        local tempDef = Mathf.Round((def))
        local tempHp = Mathf.Round((hp))
        local tempHeroNum = logicMgr.HeroPotentialMgr.HeroCrease()[star] or 1
        heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.ATK] = total[1] + tempAtk + math.floor(tempAtk*(tempHeroNum -1));
        heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.DEF] = total[2]+tempDef + math.floor(tempDef*(tempHeroNum -1));
        heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE][EnumConst.FighterAttributeEnum.HP] =  total[3] +tempHp + math.floor(tempHp*(tempHeroNum -1));
    end
end

--计算英雄装备属性
function HeroManager.processHeroEquipAttr(heroData, isother)
    --装备属性
    heroData["allAttribute"][EnumConst.AttributeTypeEnum.EQUIP] = {};
    local equipList = nil
    if isother then
        equipList = heroData.equips
    else
        equipList = logicMgr.EquipManager.getHeroEquipList(heroData["partnerId"], true);
    end
    local suit = {}
    local suitCount = {}
    local suitList = { two = {}, four = {} }
    local equips = {}
    for i = 1, #equipList do
        local equip = nil
        equip = equipList[i]
        if isother then
            equip["baseAttr"] = dataTable.getDataTableByStringId("t_equip", equip.itemModelId).f_EquipBasic
            equip.curRfLevel = equip.parameters and tonumber(decodeJsonStrToTabel(equip.parameters)["STRENGTH_LEVEL"]) or 0
        end
        if equip["baseAttr"] ~= nil then
            local attrs = decodeJsonStrToTabel(equip["baseAttr"]);
            equips[i] = {}
            local equipAttrs = equips[i]
            for j = 1, #attrs do
                local attrId = j
                local value = attrs[j]
                if type(value) == "table" then
                    attrId = value[1]
                    value = value[2]
                end
                if equipAttrs[attrId] ~= nil then
                    equipAttrs[attrId] = equipAttrs[attrId] + value;
                else
                    equipAttrs[attrId] = value;
                end
                --精炼
                local cfg = dataTable.getDataTableByMultiId("t_equiprefine", equip.itemModelId, equip.curRfLevel)
                if cfg and not string.IsNilOrEmpty(cfg.f_EquipRefineAttribute[j]) then
                    equipAttrs[attrId] = equipAttrs[attrId] + cfg.f_EquipRefineAttribute[j][2]
                end
                local tempEquipNum = 1
                if logicMgr.HeroPotentialMgr.IsAtkHpDef(attrId) then
                    tempEquipNum = logicMgr.HeroPotentialMgr.EquipCrease()[equip["quality"]] or 1
                end
                equipAttrs[attrId] = equipAttrs[attrId] + math.floor(equipAttrs[attrId]*(tempEquipNum -1))
            end
        end
        local totalCount, twoSuit, fourSuit = EquipManager.GetActiveSuitByEquipId(heroData["partnerId"], equip.itemModelId, equipList, isother)
        if totalCount >= 2 and twoSuit and not suitList.two[twoSuit] then
            suitList.two[twoSuit] = true
        end
        if totalCount >= 4 and fourSuit and not suitList.four[fourSuit] then
            suitList.four[fourSuit] = true
        end
    end
    heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP] = {}
    if equips ~= nil and #equips > 0 then
        for _,v in pairs(equips) do
            for key, value in pairs(v) do
                local temp = heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP][key]
                if temp then
                    heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP][key] = temp + value
                else
                    heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP][key] = value
                end
            end
        end
    end
    --套装属性
    local allAttr = heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP]
    local twoList = suitList.two
    local fourList = suitList.four
    for suit, v in pairs(twoList) do
        if not string.IsNilOrEmpty(suit.f_EquipSuitValue1) then
            for k2, v2 in pairs(decodeJsonStrToTabel(suit.f_EquipSuitValue1)) do
                local id = v2[1]
                local value = v2[2]
                if allAttr[id] ~= nil then
                    allAttr[id] = allAttr[id] + value;
                else
                    allAttr[id] = value;
                end
            end
        end
    end
    for suit, v in pairs(fourList) do
        if not string.IsNilOrEmpty(suit.f_EquipSuitValue2) then
            for k2, v2 in pairs(decodeJsonStrToTabel(suit.f_EquipSuitValue2)) do
                local id = v2[1]
                local value = v2[2]
                if allAttr[id] ~= nil then
                    allAttr[id] = allAttr[id] + value;
                else
                    allAttr[id] = value;
                end
            end
        end
    end
    --[[if tonumber(heroData.partnerModelId) ==13 then
        for k,v in pairs( heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP]) do
            printError("-----------------------13Equip",k,v)
        end
    end--]]
end
--专武皮肤锻造
function HeroManager.processWeaponSkin(heroData)
    heroData["allAttribute"][EnumConst.AttributeTypeEnum.WeaponSkin] = {};
    local weaponData = logicMgr.EquipManager.tabWeapon[heroData["partnerId"]];
    if weaponData == nil then
        return
    end
    local attrVlaue = G.dataTable["t_weaponrank"][tostring(heroData["partnerModelId"] * 100 + weaponData.rank)].f_WeaponRankValue
    local weaPonAttr = heroData["allAttribute"][EnumConst.AttributeTypeEnum.WeaponSkin]
    if attrVlaue ~= "" then
        for _, v in ipairs(attrVlaue) do
            weaPonAttr[v[1]] = v[2]
        end
    end
end
--计算英雄专属武器属性
function HeroManager.processHeroWeaponAttr(heroData)
    heroData["allAttribute"][EnumConst.AttributeTypeEnum.STRENGTH] = {};

    if logicMgr.EquipManager.tabWeapon == nil then
        return ;
    end

    local weaponData = logicMgr.EquipManager.tabWeapon[heroData["partnerId"]];
    if weaponData == nil then
        return
    end

    local weaponId = weaponData.weaponId;
    local weaponLv = weaponData.level;
    local items = weaponData.items;
    local weaponTable = G.dataTable["t_weapon"]

    local weaponModelId = 0;
    for key, value in pairs(weaponTable) do
        if tostring(value.f_HeroID) == tostring(heroData["partnerModelId"]) then
            weaponModelId = key;
            break ;
        end
    end

    local weaponCfg = weaponTable[tostring(weaponModelId)];
    if weaponCfg == nil then
        logError("weapon config not found. weapon id: " .. tostring(weaponId));
        return ;
    end

    local weaponAttrConfig = decodeJsonStrToTabel(weaponCfg.f_WeaponValue);

    if weaponAttrConfig == nil then
        return ;
    end
    weaponLv = weaponLv + 1 --默认零级
    if weaponLv > #weaponAttrConfig then
        weaponLv = #weaponAttrConfig
    end

    -- 武器基本属性
    local weaponAttrs = heroData["allAttribute"][EnumConst.AttributeTypeEnum.STRENGTH];
    local attribute = weaponAttrConfig[weaponLv];
    for k, v in pairs(attribute) do
        local attrId = v[1]
        local tempNum = 1
        if logicMgr.HeroPotentialMgr.IsAtkHpDef(v[1]) then
            tempNum = logicMgr.HeroPotentialMgr.WeaponCrease()
        end
        local attrNum = v[2] + math.floor(v[2] *(tempNum-1))
        weaponAttrs[attrId] = attrNum
    end

    local rank_Attr = heroData.allAttribute[EnumConst.AttributeTypeEnum.WeaponSkin] --专武锻造
    if rank_Attr then
        for k, v in pairs(rank_Attr) do
            if weaponAttrs[k] == nil then
                weaponAttrs[k] = v
            else
                weaponAttrs[k] = weaponAttrs[k] + v
            end
        end
    end

    local debris_attr = heroData.allAttribute[EnumConst.AttributeTypeEnum.Debris] --魂石
    if debris_attr then
        for k, v in pairs(debris_attr) do
            if logicMgr.HeroPotentialMgr.IsAtkHpDef(k) then
                local tempCreaseNum = logicMgr.HeroPotentialMgr.DebrisCrease()
                v = v + math.floor(v *(tempCreaseNum-1))
            end
            if weaponAttrs[k] == nil then
                weaponAttrs[k] = v
            else
                weaponAttrs[k] = weaponAttrs[k] + v
            end
        end
    end
    -- 武器镶嵌属性加成
    for i = 1, #items do
        local itemInfo = items[i];
        local params = decodeJsonStrToTabel(itemInfo.parameters)
        if params ~= nil then
            -- 属性
            -- local attrId1 = params["DEBRIS_ATTR_1"];
            -- local attrValue1 = params["DEBRIS_ATTR_VALUE_1"] or 0
            -- local attrId2 = params["DEBRIS_ATTR_2"];
            -- local attrValue2 = params["DEBRIS_ATTR_VALUE_2"] or 0

            -- weaponAttrs[attrId1] = (weaponAttrs[attrId1] or 0) + attrValue1;
            -- weaponAttrs[attrId2] = (weaponAttrs[attrId2] or 0) + attrValue2;

            -- TODO: 镶嵌道具带技能？
            --local skill1 = params["DEBRIS_SKILL_1"]
            --local skill2 = params["DEBRIS_SKILL_2"]
        end
    end
end

--计算英雄宠物属性
function HeroManager.processHeroPetAttr(heroData)
    heroData["allAttribute"][EnumConst.AttributeTypeEnum.PET] = {};

    if PetManager.petLv == nil then
        return
    end

    local elvesMergeTable = G.dataTable["t_elvesmerge"]
    if elvesMergeTable == nil then
        return
    end

    local elvesMergeCfg = elvesMergeTable[tostring(logicMgr.PetManager.petLv)];
    if elvesMergeCfg == nil then
        return
    end

    local attrConfig = decodeJsonStrToTabel(elvesMergeCfg.f_Attribute);
    if not attrConfig then
        return
    end

    -- 武器基本属性
    local petAttrs = heroData["allAttribute"][EnumConst.AttributeTypeEnum.PET];
    for _, v in pairs(attrConfig) do
        petAttrs[v[1]] = v[2]
    end
end

--计算所有英雄宠物属性
function HeroManager.processAllHeroesPetAttr()
    allHeroPetAttrDirty = {}
end

--计算英雄属性
function HeroManager.processHeroAllAttrImpl(heroData, isOther, weaponData, isChange, otherbadges)
    --总属性
    if isOther then
        local config = logicMgr.HeroManager.getHeroDatabyModelId(heroData.partnerModelId, true)
        heroData["allAttribute"] = {}
        heroData["baseAttr"] = config.baseAttr
        HeroManager.processHeroBaseAttr(heroData, heroData.level, heroData.star)
        HeroManager.processHeroEquipAttr(heroData, isOther)
        heroData.type = config["type"]
    end
    local total = heroData["totalAttribute"];
    if not total then
        total = {}
    else
        table.clear(total)
    end
    for k, v in pairs(EnumConst.FighterAttributeEnum) do
        total[v] = 0;
        for k2, v2 in pairs(EnumConst.AttributeTypeEnum) do
            if v2 ~= EnumConst.AttributeTypeEnum.Debris and v2 ~= EnumConst.AttributeTypeEnum.WeaponSkin and v2~=EnumConst.AttributeTypeEnum.Badge
            and v2 ~= EnumConst.AttributeTypeEnum.HEAD_FRAME then
                if heroData.allAttribute[v2] ~= nil and heroData.allAttribute[v2][v] ~= nil then
                    total[v] = total[v] + heroData.allAttribute[v2][v];
                end
            end
        end
    end
    local base = heroData.allAttribute[EnumConst.AttributeTypeEnum.BASE] or {};
    local equip = heroData.allAttribute[EnumConst.AttributeTypeEnum.EQUIP] or {};
    local weapon = heroData.allAttribute[EnumConst.AttributeTypeEnum.STRENGTH] or {};
    if isOther then
        base[EnumConst.FighterAttributeEnum.ATK] = base[EnumConst.FighterAttributeEnum.ATK] + weaponData[EnumConst.FighterAttributeEnum.ATK][2]
        base[EnumConst.FighterAttributeEnum.DEF] = base[EnumConst.FighterAttributeEnum.DEF] + weaponData[EnumConst.FighterAttributeEnum.DEF][2]
        base[EnumConst.FighterAttributeEnum.HP] = base[EnumConst.FighterAttributeEnum.HP] + weaponData[EnumConst.FighterAttributeEnum.HP][2]
    end
    --local fetter = heroData.allAttribute[EnumConst.AttributeTypeEnum.Fellter] or {};

    --后期如要追加额外的系统，参考天赋和羁绊在attrType中追加元素即可（无需其它操作）
    local attrType = {}
    table.insert(attrType, EnumConst.AttributeTypeEnum.BASE)
    table.insert(attrType, EnumConst.AttributeTypeEnum.EQUIP)
    table.insert(attrType, EnumConst.AttributeTypeEnum.STRENGTH)
    --table.insert(attrType, EnumConst.AttributeTypeEnum.Innate) --天赋加成
    table.insert(attrType, EnumConst.AttributeTypeEnum.Fellter) --羁绊加成
    --table.insert(attrType, EnumConst.AttributeTypeEnum.PET) --宠物加成
    --table.insert(attrType, EnumConst.AttributeTypeEnum.EQUIP_SUIT) --宠物加成
    --table.insert(attrType, EnumConst.AttributeTypeEnum.HEAD_FRAME)
    local extBaseAtkIncrease = 0
    local extEquipAtkIncrease = 0

    local extBaseDef = 0
    local extEquipDef = 0

    local extBaseHp = 0
    local extEquipHp = 0

    local allAtkPer = 0
    local residueAtk = 0 --不包含装备、基础的Atk

    local allDefPer = 0
    local residueDef = 0 --不包含装备、基础的Def

    local allHpPer = 0
    local residueHp = 0 --不包含装备、基础的HP
    for _, style in pairs(attrType) do
        local attrInfo = heroData.allAttribute[style] or {}
        --攻击（加成比）
        local atk_increase = attrInfo[EnumConst.FighterAttributeEnum.BASE_ATK_PER] or 0;
        local equip_atk_increase = attrInfo[EnumConst.FighterAttributeEnum.EQUIP_ATK_PER] or 0;

        extBaseAtkIncrease = extBaseAtkIncrease + atk_increase
        extEquipAtkIncrease = extEquipAtkIncrease + equip_atk_increase

        --防御
        local def_increase = attrInfo[EnumConst.FighterAttributeEnum.BASE_DEF_PER] or 0;
        local equip_def_increase = attrInfo[EnumConst.FighterAttributeEnum.EQUIP_DEF_PER] or 0;
        extBaseDef = extBaseDef + def_increase
        extEquipDef = extEquipDef + equip_def_increase

        --HP
        local base_hp_increase = attrInfo[EnumConst.FighterAttributeEnum.BASE_HP_PER] or 0;
        local base_equip_hp_increase = attrInfo[EnumConst.FighterAttributeEnum.EQUIP_HP_PER] or 0;
        extBaseHp = extBaseHp + base_hp_increase
        extEquipHp = extEquipHp + base_equip_hp_increase

        --计算除英雄基础属性 和 装备以外的加成
        if style ~= EnumConst.AttributeTypeEnum.BASE and style ~= EnumConst.AttributeTypeEnum.EQUIP then
            local atkValue = attrInfo[EnumConst.FighterAttributeEnum.ATK] or 0
            residueAtk = residueAtk + Mathf.Round(atkValue)

            atkValue = attrInfo[EnumConst.FighterAttributeEnum.DEF] or 0
            residueDef = residueDef + Mathf.Round(atkValue)

            atkValue = attrInfo[EnumConst.FighterAttributeEnum.HP] or 0
            residueHp = residueHp + Mathf.Round(atkValue)
        end
        local base_atk_per = attrInfo[EnumConst.FighterAttributeEnum.ATK_PER] or 0;
        local base_def_per = attrInfo[EnumConst.FighterAttributeEnum.DEF_PER] or 0;
        local base_hp_per = attrInfo[EnumConst.FighterAttributeEnum.HP_PER] or 0;
        allAtkPer = allAtkPer + base_atk_per
        allDefPer = allDefPer + base_def_per
        allHpPer = allHpPer + base_hp_per
    end
    --攻击
    local base_atk = base[EnumConst.FighterAttributeEnum.ATK] or 0
    local equip_atk = equip[EnumConst.FighterAttributeEnum.ATK] or 0

    local atk_base = base_atk * (10000 + extBaseAtkIncrease) * 0.0001
    local atk_equip = equip_atk * (10000 + extEquipAtkIncrease) * 0.0001
    local atk = atk_base +atk_equip + residueAtk

    --防御
    local base_def = base[EnumConst.FighterAttributeEnum.DEF] or 0
    local equip_def = equip[EnumConst.FighterAttributeEnum.DEF] or 0

    local def_base = base_def * (10000 + extBaseDef) / 10000
    local def_equip = equip_def * (10000 + extEquipDef) * 0.0001
    local def = def_base +def_equip + residueDef

    --HP
    local equip_hp = equip[EnumConst.FighterAttributeEnum.HP] or 0
    local base_hp = base[EnumConst.FighterAttributeEnum.HP] or 0

    local hp_base = base_hp * (10000 + extBaseHp) * 0.0001
    local hp_equip = equip_hp * (10000 + extEquipHp) * 0.0001
    local hp = hp_base + hp_equip + residueHp

    total[EnumConst.FighterAttributeEnum.ATK] = atk
    total[EnumConst.FighterAttributeEnum.DEF] = def
    total[EnumConst.FighterAttributeEnum.HP] = hp

    local hero_type = heroData.type
    local union_attr_data = unionHandler.GetUnionTechAttrValueByHeroType(hero_type)--战团科技
    if union_attr_data ~= nil then
        for k, v in pairs(union_attr_data) do
            if total[k] == nil then
                total[k] = v
            else
                total[k] = total[k] + v
            end
            allAtkPer = allAtkPer + (k==14 and v or 0)
            allDefPer = allDefPer + (k==15 and v or 0)
            allHpPer = allHpPer + (k==16 and v or 0)
        end
    end
    if not isOther then --灵赋
        local ttrs = logicMgr.HeroSoulManager.GetAllAttr()
        for k, v in pairs(ttrs) do
            --if k < 40 then
            if total[k] == nil then
                total[k] = v
            else
                total[k] = total[k] + v
            end
            --end
        end
    end
    if not isOther then
        --飞飞灵饰
        local ttrs = logicMgr.PetManager.PetPartAddAttr()
        for k, v in pairs(ttrs) do
            if total[k] == nil then
                total[k] = v
            else
                total[k] = total[k] + v
            end
            allAtkPer = allAtkPer + (k==14 and v or 0)
            allDefPer = allDefPer + (k==15 and v or 0)
            allHpPer = allHpPer + (k==16 and v or 0)
        end
    end
    if not isOther then
        local ttrs = logicMgr.HeroPotentialMgr.AddAttr()--潜能
        for k, v in pairs(ttrs) do
            if total[k] == nil then
                total[k] = v
            else
                total[k] = total[k] + v
            end
        end
    end
    if not isOther then
        local frame_attr = heroData.allAttribute[EnumConst.AttributeTypeEnum.HEAD_FRAME]--头像框
        if frame_attr then
            for k, v in pairs(frame_attr) do
                if total[k] == nil then
                    total[k] = v
                else
                    total[k] = total[k] + v
                end
            end
        end
    else
        local config = G.dataTable["t_headframe"][tostring(heroData.picFrame)]
        if config then
            local tb = config.f_CharacterValue
            if type(tb) == "table" then
                for k, v in pairs(tb) do
                    total[v[1]] = total[v[1]] + v[2]
                end
            end
        end
    end
    if not isOther then
    else
        local weaPonRankAttr = G.dataTable["t_weaponrank"][tostring(heroData.partnerModelId * 100 + heroData.weaponInfo.rank)].f_WeaponRankValue
        if weaPonRankAttr and weaPonRankAttr ~= "" then
            for k, v in pairs(weaPonRankAttr) do
                if total[v[1]] == nil then
                    total[v[1]] = v[2]
                else
                    total[v[1]] = total[k] + v[2]
                end
            end
        end
    end
    if isOther then
        if heroData.weaponInfo.items[1] and heroData.weaponInfo.items[1].parameters then
            local js = decodeJsonStrToTabel(heroData.weaponInfo.items[1].parameters)
            local level = js.DEBRIS_LV and tonumber(js.DEBRIS_LV) or 1
            local skillId = G.dataTable["t_debris"][tostring(heroData.weaponInfo.items[1].itemModelId)].f_SkillId
            local cg = dataTable.getDataTableByStringId("t_debrismajorskill",skillId + level)
            for k, v in pairs(cg.f_DebrisBasic) do
                if total[v[1]] then
                    total[v[1]] = total[v[1]] + v[2]
                else
                    total[v[1]] = {}
                    total[v[1]] = v[2]
                end
            end
        end
    end
    if not isOther then
        local badge_attr = heroData.allAttribute[EnumConst.AttributeTypeEnum.Badge] --徽章
        if badge_attr then
            for k, v in pairs(badge_attr) do
                if total[k] == nil then
                    total[k] = v
                else
                    total[k] = total[k] + v
                end
                allAtkPer = allAtkPer + (k==14 and v or 0)
                allDefPer = allDefPer + (k==15 and v or 0)
                allHpPer = allHpPer + (k==16 and v or 0)
            end
        end
    else
        if otherbadges and #otherbadges > 0 then
            for k, v in pairs(otherbadges) do
                local oneAttr = decodeJsonStrToTabel(G.dataTable["t_medal"][tostring(v)].f_CharacterValue)
                for m, n in pairs(oneAttr) do
                    if total[n[1]] then
                        total[n[1]] = total[n[1]] + n[2]
                    else
                        total[n[1]] = {}
                        total[n[1]] = n[2]
                    end
                end
            end
        end
    end
    if not isOther then
        local skinData  = logicMgr.SkinManager.getHeroSkinSrvInfo(heroData.partnerModelId)
        if table.getn(skinData) > 0 then
            for k,v in pairs(skinData) do
                local attrs = dataTable.getDataTableByStringId("t_skin",tostring(k))
                if attrs and attrs.f_SkinAttribute then
                    for _,value in pairs(attrs.f_SkinAttribute) do
                        if total[value[1]] then
                            total[value[1]] = total[value[1]] + value[2]
                        else
                            total[value[1]] = value[2]
                        end
                        allAtkPer = allAtkPer + (value[1]==14 and value[2] or 0)
                        allDefPer = allDefPer + (value[1]==15 and value[2] or 0)
                        allHpPer = allHpPer + (value[1]==16 and value[2] or 0)
                    end
                end
            end
        end
    end
    if not isOther then
        local runeData = logicMgr.RuneManager.GetHeroRuneSrvInfo(heroData.partnerId)
        if runeData then
            for k,v in pairs(runeData) do
                local attrs = v.totalAttr
                if attrs then
                    for key,value in pairs(attrs) do
                        --if total[value[1]] then
                        --    total[value[1]] = total[value[1]] + value[2]
                        --else
                        --    total[value[1]] = value[2]
                        --end

                        if total[key] then
                            total[key] = total[key] + value
                        else
                            total[key] = value
                        end
                        allAtkPer = allAtkPer + (key==14 and value or 0)
                        allDefPer = allDefPer + (key==15 and value or 0)
                        allHpPer = allHpPer + (key==16 and value or 0)
                    end
                end
            end
        end
    end
    if not isOther then
        local attrData = logicMgr.HeroManorManager.getAllAttrByMaster(heroData.partnerId)
        if attrData then
            for k,v in pairs(attrData) do
                if total[k] then
                    total[k] = total[k] + v
                else
                    total[k] = v
                end
                allAtkPer = allAtkPer + (k==14 and v or 0)
                allDefPer = allDefPer + (k==15 and v or 0)
                allHpPer = allHpPer + (k==16 and v or 0)
            end
        end
    end
    total[EnumConst.FighterAttributeEnum.ATK] = total[EnumConst.FighterAttributeEnum.ATK] +math.floor(total[EnumConst.FighterAttributeEnum.ATK]* allAtkPer* 0.0001)
    total[EnumConst.FighterAttributeEnum.DEF] =total[EnumConst.FighterAttributeEnum.DEF]+ math.floor(total[EnumConst.FighterAttributeEnum.DEF]*allDefPer* 0.0001)
    total[EnumConst.FighterAttributeEnum.HP] = total[EnumConst.FighterAttributeEnum.HP]+math.floor(total[EnumConst.FighterAttributeEnum.HP]*allHpPer* 0.0001)
    if isOther then
        return total
    else
        heroData["totalAttribute"] = total
    end
    if isChange then
        --heroData["power"] = this.processPower(total, heroData.type)
        --print("power"..heroData["power"])
    end
end

function HeroManager.CalcHeroPowerByAttrs(partnerId,data)
    local heroData = tabKeyMap[tostring(partnerId)]
    if data then
        heroData = data
    end
    local partA = 0
    local partB= 1
    for k,v in pairs(heroData["totalAttribute"]) do
        local cfg = attributeLibCfg[tostring(k)]
        local temp = cfg.f_AttributeType == 1 and v or v / 10000
        --[[if tonumber(heroData.partnerModelId)== 13 then
            printError("-----------------------13",k,v)
        end--]]
        if cfg.f_AttributeType == 1 then
            local numA = temp
            partA = partA + cfg["f_AttributeValueCE_"..heroData.type] / 10000* numA
        else
            local numB = temp
            if k == 28 then
                numB = temp - 1
            end
            partB = partB + cfg["f_AttributeValueCE_"..heroData.type] / 10000 * numB
        end
    end
    local num = logicMgr.SkillManager.SkillAddPower(heroData.partnerModelId,this.getHeroShowLevelByPartnerId(heroData.partnerId),heroData.quality)
    --[[if tonumber(heroData.partnerModelId)== 13 then
        printError("-----------------------13partA",partA,partB,num)
    end--]]
    return Mathf.Round((partA * partB)*(1+num))
end

function HeroManager.processHeroAllAttr(heroData, isChange)
    --总属性
    this.processHeroAllAttrImpl(heroData, nil, nil, isChange)

end
--总战力
function HeroManager.GetHerosSumPower(isAll)
    local list = this.getOwnerHeroListReadOnly()
    local sumPower = 0
    table.sort(list,function(a,b)
        return a["realPower"] > b["realPower"]
    end)
    if isAll then
        for _, v in pairs(list) do
            -- 总战力排除智慧之链的影响
            --sumPower = sumPower + v["power"]
            if v["realPower"] ~= nil then
                sumPower = sumPower + v["realPower"]
            else
                local partnerId = v["partnerId"];
                local partnerModelId = v["partnerModelId"];
                Util.LogError("partnerId = " .. partnerId .. "  partnerModelId = " .. partnerModelId .. "丢了 realPower 字段");
            end
        end
    else
        for i=1,6 do
            if list[i] then
                sumPower = sumPower + list[i]["realPower"]
            end
        end
        --printError("============================sumPower",sumPower)
        this.SetRoleInfo("maxPower", sumPower);
    end
    return Mathf.Round(sumPower)
end
function HeroManager.processPower(attributes, carrer)
    local power = 0;
    if attributes ~= nil then
        local a = 0
        local b = 0
        local ceKey = "f_AttributeValueCE_" .. carrer
        for key, value in pairs(attributes) do
            local attrCfg = attributeLibCfg[tostring(key)];
            local defaultCE = attrCfg[ceKey]
            if attrCfg.f_AttributeType == 1 then
                a = a + value * defaultCE / 10000;
            else
                if b == 0 then
                    b = 1 + value / 10000 * defaultCE / 10000;
                else
                    if attrCfg.f_AttributeID == 28 then
                        b = b * (1 + (value - 10000) / 10000 * defaultCE / 10000);
                    else
                        b = b * (1 + value / 10000 * defaultCE / 10000);
                    end

                end
            end
        end
        if a == 0 then
            power = Mathf.Round(b)
        elseif b == 0 then
            power = Mathf.Round(a)
        else
            power = Mathf.Round(a * b)
        end
    end
    return power;
end

function HeroManager.MaxLevel()
    local db = dataTable.getDataTable("t_levelupattribute");
    local length = table.getn(db);
    return db[tostringMy(length)]["f_CharacterLevel"];
end

--英雄排序
function HeroManager.sortLockedHero(a, b)
    --未解锁英雄排序
    local hero1 = logicMgr.HeroManager.getHeroDatabyModelId(tostring(a.partnerModelId), true)
    local ownNum1 = ItemManager.getItemCountbyModelId(hero1.storeId)
    local needNum1 = G.dataTable["t_hero"][tostring(a.partnerModelId)].f_ActiveCount

    local hero2 = logicMgr.HeroManager.getHeroDatabyModelId(tostring(b.partnerModelId), true)
    local ownNum2 = ItemManager.getItemCountbyModelId(hero2.storeId)
    local needNum2 = G.dataTable["t_hero"][tostring(b.partnerModelId)].f_ActiveCount
    local flag1 = ownNum1 >= needNum1
    local flag2 = ownNum2 >= needNum2
    if flag1 ~= flag2 then
        return flag1
    else
        if this._factionSortList[a["faction"] + 1] ~= this._factionSortList[b["faction"] + 1] then
            return this._factionSortList[a["faction"] + 1] > this._factionSortList[b["faction"] + 1]
        else
            return this.sortHero(a, b)
        end
    end
end
function HeroManager.sortHero(a, b)
    if this.getHeroShowLevelByPartnerId(a.partnerId) ~= 0 then
        a["level2"] = this.getHeroShowLevelByPartnerId(a.partnerId);
    else
        a["level2"] = 0;
    end
    if this.getHeroShowLevelByPartnerId(b.partnerId) ~= 0 then
        b["level2"] = this.getHeroShowLevelByPartnerId(b.partnerId);
    else
        b["level2"] = 0;
    end

    if a["level2"] > b["level2"] then
        return true;
    elseif a["level2"] == b["level2"] then
        if a["star"] > b["star"] then
            return true;
        elseif a["star"] == b["star"] then
            if this.HeroTypeList[a["type"]] > this.HeroTypeList[b["type"]] then
                return true
            elseif this.HeroTypeList[a["type"]] == this.HeroTypeList[b["type"]] then
                return tonumber(a["partnerModelId"]) < tonumber(b["partnerModelId"]);
            else
                return false
            end
        else
            return false;
        end
    else
        return false;
    end
end

function HeroManager.getSortHeroByType()
    local HeroSortType = this.HeroSortType
    HeroManager.sortType = 1;--英雄排序类型
    if GetPlayerPrefs("CharactorMainSortOrder") then
        HeroManager.sortType = tonumber(GetPlayerPrefs("CharactorMainSortOrder"));--英雄排序类型
    end
    local sort = logicMgr.HeroManager.sortHeroWithPower
    if HeroManager.sortType == HeroSortType.power then
        sort = logicMgr.HeroManager.sortHeroWithPower
    elseif HeroManager.sortType == HeroSortType.quality then
        sort = logicMgr.HeroManager.sortHeroWithQuality
    else
        sort = logicMgr.HeroManager.sortHeroWithLevel
    end
    return sort;
end

function HeroManager.sortHeroWithPower(a, b)
    local powerA = tonumber(tostring(this.GetHeroPower(a.partnerId)))
    local powerB = tonumber(tostring(this.GetHeroPower(b.partnerId)))
    if powerA == powerB then
        return this.sortHero(a, b)
    elseif powerA == nil or powerB == nil then
        if (powerA == nil) then
            return false
        else
            return true
        end
    elseif powerA > powerB then
        return true
    else
        return false
    end
end
function HeroManager.sortHeroWithQuality(a, b)
    local qualityA = a.star
    local qualityB = b.star
    if qualityA == qualityB then
        return this.sortHero(a, b)
    elseif qualityA > qualityB then
        return true
    else
        return false
    end
end
function HeroManager.sortHeroWithLevel(a, b)
    return this.sortHero(a, b)
end

function HeroManager.PrepareForHeroLinkSort()

end
function HeroManager.sortHeroWithLink(a, b)
end


--账号唯一id
function HeroManager.GetRoleId()
    if G.serverData["roleInfo"] and G.serverData["roleInfo"].show and G.serverData["roleInfo"].show.playerId then
        return G.serverData["roleInfo"].show.playerId
    else
        --print("playerId is empty, skillEditor do not care");
        return "";
    end

end

--传入的id是否是自己的
function HeroManager.CompareMineId(id)
    return tostring(id) == tostring(HeroManager.GetRoleId())
end

--- 角色信息 playerId name等
function HeroManager.GetRoleInfo(param)
    if G.serverData["roleInfo"] == nil then
        if param == "playerId" then
            return 0;
        end
        return nil;
    end
    if param == nil then
        return G.serverData["roleInfo"]["show"]
    else
        if param == 'pic' then
            return checkHeroSkinId(G.serverData["roleInfo"]["show"][param])
        end
        return G.serverData["roleInfo"]["show"][param]
    end
end

function HeroManager.InitRoleInfo(info)
    G.serverData["roleInfo"]["show"] = info
    this.SetLastPlayerLevel(this.GetRoleLevel());
end

function HeroManager.SetRoleInfo(param, value)
    if G.serverData["roleInfo"]["show"][param] then
        G.serverData["roleInfo"]["show"][param] = value
    end
end
--专武品质
function HeroManager.GetWeaponQuality(modeld)
    if not modeld then
        modeld = HeroManager.GetRoleHeadID()
    end
    return EquipManager.getWeaponLevelByModelId(modeld, true)
end
--- 获取等级
function HeroManager.GetRoleLevel()
    if G.serverData["roleInfo"] and G.serverData["roleInfo"].show and G.serverData["roleInfo"].show.level then
        return G.serverData["roleInfo"].show.level
    else
        print("playerId is empty, skillEditor do not care");
        return 500;
    end
end

--- 获取头像
function HeroManager.GetRoleIcon(skinId)
    local heroInfo = dataTable.getRow("t_hero", HeroManager.GetRoleHeadID())
    local path = ""
    if heroInfo then
        path = EnumConst.AtlasPath.ICONAtlas .. heroInfo["f_HeroIcon"]
    end
    if skinId and tonumber(skinId) > 0 then
        skinId = checkHeroSkinId(skinId)
        skinId = tonumber(skinId)
        local isOrignalSkin = G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0   --是否原皮
        if not isOrignalSkin then
            path = dataTable.getDataTableByStringId("t_skin", skinId, "f_HeroIcon")
        end
    end
    return path
end
--- 获取头像框
function HeroManager.GetRoleHeadFrame()
    return G.serverData["roleInfo"].show.picFrame
end
--- 获取头像ID(对应hero表中的f_HeroID)
function HeroManager.GetRoleHeadID()
    return G.serverData["roleInfo"].show.headID or HelperFunc.GetGlobalNumVlue(100)
end

function HeroManager.SetRoleHeadID(heroCfgID)
    G.serverData["roleInfo"].show.headID = heroCfgID
end

--- 获取名称
function HeroManager.GetRoleName()
    if G.serverData["roleInfo"] and G.serverData["roleInfo"].show and G.serverData["roleInfo"].show.name then
        return G.serverData["roleInfo"].show.name
    else
        print("playerId is empty, skillEditor do not care");
        return ""
    end
end
--获取玩家性别
function HeroManager.GetRoleSex()
    return G.serverData["roleInfo"].show.sex
end
--获取star大于某个值
function HeroManager.GetHerosByStar(num)
    local tempOwner = logicMgr.HeroManager.getOwnerHeroList(false, nil, true);
    local count = 0
    for _, v in pairs(tempOwner) do
        if v.star == num then
            count = count + 1
        end
    end
    return count
end
function HeroManager.GetAllHero(own, unOwn)
    table.clear(tabOwner)
    table.clear(tabUnOwner)
    if own then
        local tempOwner = logicMgr.HeroManager.getOwnerHeroList(false, nil, true);
        for i = 1, #tempOwner do
            if tempOwner[i]["category"] ~= 2 and tempOwner[i]["category"] ~= 3 then
                table.insert(tabOwner, tempOwner[i]);
            end
        end
        table.sort(tabOwner, logicMgr.HeroManager.sortHero);
    end
    if unOwn then
        local tempUnOwner = logicMgr.HeroManager.getUnOwnerHeroList();
        for i = 1, #tempUnOwner do
            if tempUnOwner[i]["category"] ~= 2 and tempUnOwner[i]["category"] ~= 3 then
                table.insert(tabUnOwner, tempUnOwner[i]);
            end
        end
        table.sort(tabUnOwner, logicMgr.HeroManager.sortHero);
    end

    return tabOwner, tabUnOwner;
end

--------------弃用   新版没有主角英雄的概念了-----------------
--通过modelId设置角色partnerId
function HeroManager.setMySelfPartnerId()
    local initHeroCfg = HeroManager.GetBornHeroCfgTbale()
    if initHeroCfg then
        for _, v in pairs(initHeroCfg) do
            mySelfModelId = v
            break
        end
    end
    --printError("setMySelfPartnerId()该函数已弃用, 请大家自行修改相关函数(取消主角的概念，全部统一为伙伴（英雄)")

    local mySelf = nil;
    --mySelfId = tostring(partnerId);
    for i = 1, #tabAllHero do
        local hero = tabAllHero[i];
        if hero["partnerModelId"] == tostring(mySelfModelId) then
            mySelf = hero;
            --mySelf["partnerId"] = mySelfId;
            break ;
        end
    end
    --tabKeyMap[mySelfId] = mySelf;
end

--获取角色数据(之前是用来获取 英杰卡的信息， 现在英杰取消了  此函数应该不会被调用才对)
function HeroManager.getMyself(shoTips)
    if shoTips == nil then
        printError("getMyself()该函数已弃用, 请大家自行修改相关函数(取消主角的概念，全部统一为伙伴（英雄)")
    end

    --为了避免报错  临时处理
    return clone(HeroManager.getHeroDatabyModelId(mySelfModelId, true))
    --return clone(tabKeyMap[mySelfId]) 以前的代码
end

function HeroManager.getMyselfNotClone()
    printError("getMyselfNotClone()该函数已弃用, 请大家自行修改相关函数(取消主角的概念，全部统一为伙伴（英雄)")
    --为了避免报错  临时处理
    return HeroManager.getHeroDatabyModelId(mySelfModelId)
    --return tabKeyMap[mySelfId]; 以前的代码
end

--设置模仿技能
function HeroManager.setImitationSkill(skillId)
    local skillField = logicMgr.SkillManager.getSkilField(skillId);
    local hero = HeroManager.getMyselfNotClone()--为了避免报错  临时处理
    --local hero = tabKeyMap[mySelfId];
    local skills = hero["skillIds"];
    local added = false;
    for i = 1, #skills do
        if skillField == logicMgr.SkillManager.getSkilField(skills[i]) then
            skills[i] = skillId;
            added = true;
            break ;
        end
    end
    if added == false then
        table.insert(skills, skillId);
    end
    hero["skillIds"] = skills;
    printError("setImitationSkill(skillId)该函数已弃用, 请大家自行修改相关函数(取消主角的概念，全部统一为伙伴（英雄)")
end
---公告排行榜排名第一雕像
function HeroManager.SetCityShowFirstRankPlayer(info)
    if info then
        this.firstRankCityShowPlayer.id = tostring(info.playerId)
        this.firstRankCityShowPlayer.name = info.name
    else
        this.firstRankCityShowPlayer.id = "0"
    end
end
function HeroManager.GetCityShowFirstRankPlayer()
    return this.firstRankCityShowPlayer
end

function HeroManager.ClerPool()
    --[[
    if upPool and #upPool > 0 then
        for _, v in pairs(upPool) do
            if v then
                v:Dispose();
            end
        end
        upPool = {};
        obj = nil;
    end
    ]]
    upPoolNum = 0
    if upPool1 ~= nil then
        upPool1:Dispose();
        upPool1 = nil
    end
    if upPool2 ~= nil then
        upPool2:Dispose();
        upPool2 = nil
    end
    if upPool3 ~= nil then
        upPool3:Dispose();
        upPool3 = nil
    end
    if upPool4 ~= nil then
        upPool4:Dispose();
        upPool4 = nil
    end
    if upPool5 ~= nil then
        upPool5:Dispose();
        upPool5 = nil
    end
    if upPool6 ~= nil then
        upPool6:Dispose();
        upPool6 = nil
    end
    if upPool7 ~= nil then
        upPool7:Dispose();
        upPool7 = nil
    end
    if upPool8 ~= nil then
        upPool8:Dispose();
        upPool8 = nil
    end
end

function HeroManager.SkinData(heroId)
    local data = {};
    local configs = G.dataTable["t_skin"]
    for _, v in pairs(configs) do
        if v["f_HeroID"] == tonumber(heroId) then
            v.isHave = nil
            v.overtime = nil
            v.status = nil   --使用中
            table.insert(data, v);
        end
    end
    return data;
end

function HeroManager.SetLastPlayerLevel(level)
    this.lastPlayerLevel = level;
end

function HeroManager.GetLastPlayerLevel()
    return this.lastPlayerLevel;
end

function HeroManager.HeroPlayCV(heroId, actionType)
    --[[local data = {}
    local value = {};
    local configs = G.dataTable["t_interaction"]
    for _, v in pairs(configs) do
        if v["f_HeroID"] == tonumber(heroId) and actionType == v["f_ActionType"] then
            table.insert(data, v)
        end
    end
    if #data > 0 then
        if #data > 1 then
            local index = math.random(1, #data)
            value = data[index];
        else
            value = data[1];
        end
        soundMgr:PlayCV("sound/cv/" .. value.f_Voice, nil);
    end--]]
end
-------------------------------------------------
function HeroManager.addDrawNeedShowItems(items, clips)
    if this.drawNeedShowItems == nil then
        this.drawNeedShowItems = {};
    end
    if this.heroClips == nil then
        this.heroClips = {}
    end
    local flag = false;
    for k, v in pairs(items) do
        flag = false;
        for key, value in pairs(this.drawNeedShowItems) do
            if value.itemModelId == v[1] then
                value.num = value.num + v[2];
                flag = true;
                break ;
            end
        end
        if not flag then
            local itemData = logicMgr.CostManager.getItemOrEquipDataByIdAndNum(v[1], v[2]);
            if itemData ~= nil then
                table.insert(this.drawNeedShowItems, itemData);
            end
        end
    end
    for k, v in pairs(clips) do
        if this.heroClips[k] then
            this.heroClips[k] = this.heroClips[k] + v
        else
            this.heroClips[k] = v
        end
    end
end
--
--function HeroManager.showDrawWnd(curShowCardNum)
--    local itemGetCb= function(flag)
--        if flag == 1 then
--            if logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.HeroShop, true) then
--                showUI(PanelNames.UIShop, EnumConst.ShopType.heroShop, function()
--                    shopHandler.reqShopDataList(11000);
--                end, 6);
--            end
--        end
--        this.clearDrawNeedShowItems();
--    end
--    local haveSoul=(curShowCardNum ~= 1 or not logicMgr.GuideMgr.IsGuiding())
--            and (this.drawNeedShowItems ~= nil and #this.drawNeedShowItems > 0) --存在镜魂
--    if haveSoul then
--        if drawHandler.isShowDPReward then
--            showUI(PanelNames.UICommonItemGet, nil, nil, 4, this.drawNeedShowItems,itemGetCb, getLanguage("Sys_Draw_AutoTrans"), nil, true,drawHandler.dpRewards);
--        else
--            showUI(PanelNames.UICommonItemGet, nil, nil, 3, this.drawNeedShowItems,itemGetCb, getLanguage("Sys_Draw_AutoTrans"), nil, true);
--        end
--    else
--        if drawHandler.isShowDPReward then
--            showUI(PanelNames.UICommonItemGet, nil, nil, 4,nil,nil, nil, nil, true,drawHandler.dpRewards);
--        end
--    end
--    if not(curShowCardNum ~= 1 or not logicMgr.GuideMgr.IsGuiding())then
--        this.clearDrawNeedShowItems()
--    end
--    drawHandler.ClearDpReward()
--end
function HeroManager.showDrawInfoWnd(cardNum)
    if not (cardNum ~= 1 or not logicMgr.GuideMgr.IsGuiding()) then
        this.clearDrawNeedShowItems()
        return
    end
    local type = nil
    local flag1 = this.drawNeedShowItems ~= nil and #this.drawNeedShowItems > 0
    local flag2 = this.heroClips ~= nil and table.getn(this.heroClips) > 0
    if flag1 and flag2 then
        type = EnumConst.DrawResultType.SpecialAndClips
    elseif flag1 then
        type = EnumConst.DrawResultType.SpecialAward
    elseif flag2 then
        type = EnumConst.DrawResultType.HeroClips
    end
    local info = {}
    info.specialAwards = this.drawNeedShowItems
    info.heroClips = this.heroClips
    if type then
        showUI(PanelNames.UICommonDrawItemGet, type, info);
    else
        if drawHandler.drawProcessMsg then
            FireEvent(Config.EventType.Fresh_DrawProcess, drawHandler.drawProcessMsg)
            drawHandler.ClearDpReward()
        end
    end
    logicMgr.HeroManager.clearDrawNeedShowItems()
end
function HeroManager.clearDrawNeedShowItems()
    this.drawNeedShowItems = nil;
    this.heroClips = nil
end

---返回:等级,类型(0不在智慧之链上,1主英雄,2在智慧之链上,3巅峰等级)
function HeroManager.getHeroShowLevelByPartnerId(id)
    local data = tabKeyMap[id]--this.getHeroDatabyPartnerId(id, true);
    local level, phase = 0
    if data == nil then
        return 0, 0, phase;
    end
    if logicMgr.HeroLinkManager.isInLink(id, false) then
        level, phase = logicMgr.HeroLinkManager.GetHeroLevelByType()
        if HeroLinkManager.IsTopLevelOpen() then
            return level, 3, phase;
        end
        return level, 2, phase;
    end
    if logicMgr.HeroLinkManager.isMainHero(id) and logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.HeroLink) then
        if HeroManager.IsMaxLevel(data.level) and HeroLinkManager.IsTopLevelOpen() then
            local topLevel, phase = HeroLinkManager.GetTopLevel()
            return topLevel, 3, phase
        end
        return data.level, 1, phase;
    end
    return data.level, 0, phase;
end

--- 当存在跳转时,先关自己再打开跳转(先设为nil,再设为true)
function HeroManager.setGetNewHeroShow(isShow)
    this.getNewHeroShow = isShow;
end

function HeroManager.showNewHero(callBack, heroSource)
    if this.needShowHeroList ~= nil and #this.needShowHeroList > 0 then
        --英雄激活TA
        HeroManager.SetNewHeroTA(this.needShowHeroList[1][1], heroSource)
        this.needShowHeroList[1][2] = this.GetHeroStar(this.needShowHeroList[1][3]);
        showUI(PanelNames.UIDrawAnimation, this.needShowHeroList[1], nil, false, function()
            table.remove(this.needShowHeroList, 1);
            logicMgr.HeroManager.showNewHero(callBack, heroSource);
        end, nil, true);
        return true
    else
        if isOpenUI(PanelNames.UIDrawAnimation) then
            closeUI(PanelNames.UIDrawAnimation);
        end
        this.needShowHeroList = nil;
        if callBack then
            callBack();
        end
        return false
    end
end

function HeroManager.showLocalityUIByName(key, uiName, callBack)
    if key == nil or uiName == nil then
        if callBack ~= nil then
            callBack();
        end
        return ;
    end
    key = key .. logicMgr.HeroManager.GetRoleInfo("playerId");
    local lastTime = Util.GetPlayerPrefs(key);
    if lastTime == nil then
        Util.SetPlayerPrefs(key, 1);
        showUI(uiName, callBack);
    else
        if callBack ~= nil then
            callBack();
        end
    end
end

--设置新英雄的埋点
function HeroManager.SetNewHeroTA(partnerModelId, heroSource)
    for partnerId, heroInfo in pairs(tabKeyMap) do
        if heroInfo.partnerModelId == partnerModelId then
            local _newHeroDic = {}
            _newHeroDic.hero_uniqueid = partnerId
            _newHeroDic.hero_id = partnerModelId
            _newHeroDic.source = heroSource
            _newHeroDic.hero_level = this.GetHeroLevel(partnerId)
            _newHeroDic.hero_star = this.GetHeroStar(partnerId)
            _newHeroDic.same_number = this.GetHeroSameNum(partnerId)
            _newHeroDic.info_ex = -1
            TAManager.TrackByDictionary("add_hero", _newHeroDic)
        end
    end
end

--各类型英雄是否达到限制等级
function HeroManager.IsAllTypeHeroReachLimitLevel()
    --local tb = TablePool.Get()
    --for i = 1, 6 do
    --    -- 6职业
    --    tb[i] = 0
    --end
    --for k, v in pairs(tabKeyMap) do
    --    if tb[v.type] then
    --        tb[v.type] = math.max(tb[v.type], v.level)
    --    else
    --        tb[v.type] = v.level
    --    end
    --end
    --local min = -1
    --for k, v in pairs(tb) do
    --    if min == -1 then
    --        min = v
    --    else
    --        min = math.min(min, v)
    --    end
    --end
    --TablePool.Release(tb)
    return logicMgr.HeroLinkManager.GetHeroLevel() >= this.GetLimitLevel()
end
--英雄限制等级
function HeroManager.GetLimitLevel()
    return dataTable.getGlobalInt(250)
end
function HeroManager.IsMaxLevel(level)
    return level >= this.GetLimitLevel()
end

function HeroManager.GetHeroLocationResize(modelId)
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return nil, nil
    end
    if AppConst.drawingState == 0 then
        --普通模式
        local resize = decodeJsonStrToTabel(cfg.f_Resize);
        local location = decodeJsonStrToTabel(cfg.f_Location);
        return resize, location
    else
        local resize = decodeJsonStrToTabel(cfg.f_ResizePA);
        local location = decodeJsonStrToTabel(cfg.f_LocationPA);
        return resize, location
    end


end

function HeroManager.GetHeroLocationResizeBySkinId(skinId)
    local cfg = dataTable.getDataTableByStringId("t_skin", skinId)
    if not cfg then
        return nil, nil
    end
    if AppConst.drawingState == 0 then
        --普通模式
        local resize = decodeJsonStrToTabel(cfg.f_Resize);
        local location = decodeJsonStrToTabel(cfg.f_Location);
        return resize, location
    else
        local resize = decodeJsonStrToTabel(cfg.f_ResizePA);
        local location = decodeJsonStrToTabel(cfg.f_LocationPA);
        return resize, location
    end


end

function HeroManager.GetHeroSupShowLocationResizeBySkinId(skinId)
    local cfg = dataTable.getDataTableByStringId("t_skin", skinId)
    if not cfg then
        return nil, nil
    end
    if AppConst.drawingState == 0 then
        --普通模式
        local resize = decodeJsonStrToTabel(cfg.f_FightResize);
        local location = decodeJsonStrToTabel(cfg.f_FightLocation);
        return resize, location
    else
        local resize = decodeJsonStrToTabel(cfg.f_FightResizePA);
        local location = decodeJsonStrToTabel(cfg.f_FightLocationPA);
        return resize, location
    end


end

--雕像排行榜立绘大小
function HeroManager.GetHeroRanksize(modelId)
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return nil, nil
    end

    --普通模式
    local resize = decodeJsonStrToTabel(cfg.f_Ranksize);
    local location = decodeJsonStrToTabel(cfg.f_RankLocation);
    local offset = decodeJsonStrToTabel(cfg.f_RankPos);
    return resize, location, offset

end

--英雄小人
function HeroManager.GetHeroDrawingRolePath(modelId, defaultDrawing, skinId)
    if defaultDrawing == nil then
        defaultDrawing = ""
    end
    modelId = tostring(modelId);
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return defaultDrawing
    end
    defaultDrawing = "Model/Role/" .. cfg.f_HeroModel
    if AppConst.drawingState == 0 then
        --普通模式
        if cfg.f_HeroModel == "" then
            defaultDrawing = ""
            printError("modelId=={}, cfg.f_HeroModel == empty", modelId)
        end
    else
        --和谐模式
        if cfg.f_HeroModelPA == "" then
            --没有，就使用非和谐版
        else
            defaultDrawing = "Model/Role_PA/" .. cfg.f_HeroModelPA
        end
    end
    if skinId and skinId > 0 then
        skinId = tonumber(skinId)
        local isOrignalSkin = G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0   --是否原皮
        if not isOrignalSkin then
            defaultDrawing = defaultDrawing .. "-" .. skinId;
        end
    end
    return defaultDrawing
end

--英雄立绘
function HeroManager.GetHeroDrawingPath(modelId, defaultDrawing, skinId)
    if defaultDrawing == nil then
        defaultDrawing = ""
    end
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return defaultDrawing
    end
    defaultDrawing = "Model/Drawing/" .. cfg.f_HeroDrawing
    if AppConst.drawingState == 0 then
        --普通模式
        if cfg.f_HeroDrawing == "" then
            return ""
        end
    else
        --和谐模式
        if cfg.f_HeroDrawingPA == "" then
            return ""
        else
            defaultDrawing = "Model/" .. cfg.f_HeroDrawingPA
        end
    end
    if skinId and tonumber(skinId) > 0 then
        skinId = tonumber(skinId)
        local isOrignalSkin = G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0   --是否原皮
        if not isOrignalSkin then
            defaultDrawing = defaultDrawing .. "-" .. skinId;
        end
    end
    return defaultDrawing
end

--英雄卡面
function HeroManager.GetHeroBIcon(modelId, skinId)
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return ""
    end
    local path = cfg.f_HeroBIcon
    if AppConst.drawingState == 0 then
        --普通模式
        -- cfg.f_HeroBIcon
    else
        --和谐模式
        path = cfg.f_HeroBIconPA
    end
    if skinId and tonumber(skinId) > 0 then
        skinId = tonumber(skinId)
        local isOrignalSkin = G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0   --是否原皮
        if not isOrignalSkin then
            path = path .. "-" .. skinId;
        end
    end
    return path
end
--英雄race
function HeroManager.GetHeroRace(modelId)
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return 0
    end
    return cfg.f_HeroRace
end
--英雄势力
function HeroManager.GetHeroFactionType(modelId)
    local cfg = dataTable.getDataTableByStringId("t_hero", modelId)
    if not cfg then
        return 0
    end
    return cfg.f_FactionType
end
--计算羁绊总加成
--返回的列表{1：攻击{attrId：属性id , attrNum：值}，2：防御 ，3：血}
function HeroManager.GetCalculateAllAttr()
    local tableHeros = this.getOwnerHeroList(false, nil, true)
    fetterAttrList = {}
    fetterAttrList[1] = { attrId = 1, attrNum = 0 }
    fetterAttrList[2] = { attrId = 2, attrNum = 0 }
    fetterAttrList[3] = { attrId = 3, attrNum = 0 }
    for _, heroInfo in pairs(tableHeros) do
        if heroInfo["fetter"] then
            for _, fetterID in pairs(heroInfo["fetter"]) do
                local cfgInfo = G.dataTable["t_trammel"][tostring(fetterID)]
                if cfgInfo then
                    local attrList = decodeJsonStrToTabel(cfgInfo["f_AttributeBonus"])
                    if attrList then
                        for _, v in pairs(attrList) do
                            local attrId = v[1]
                            local attrNum = v[2]
                            if fetterAttrList[attrId] == nil then
                                fetterAttrList[attrId] = { attrId = attrId, attrNum = attrNum }
                            else
                                fetterAttrList[attrId] = { attrId = attrId, attrNum = fetterAttrList[attrId]["attrNum"] + attrNum }
                            end
                        end
                    end
                end
            end
        end
    end
    -- 默认显示攻防血
    --if #fetterAttrList < 1 then
    --    fetterAttrList[1] = { attrId = 1, attrNum = 0 }
    --    fetterAttrList[2] = { attrId = 2, attrNum = 0 }
    --    fetterAttrList[3] = { attrId = 3, attrNum = 0 }
    --end
    return fetterAttrList;
end
function HeroManager.OnDestroy()
    dungeonHandler.hardData = {}
    this.chooseHeroMap = {};
    table.clear(tabAllHero)
    table.clear(tabKeyMap)
    if this.utimeOnline then
        utimer.remove(this.utimeOnline);
        this.utimeOnline = nil;
    end
    this.OnlineTimeNode = nil;
    this.drawTodayCountList = nil;
    this.SetLastDrawNum();
    partnerHandler.interactionSaveData = {
        isEffective = false,
        partnerDatas = {}, --partnerId=0,lastLevel=0,lastExp=0
        interactionId = 0,
        isBattle = false,
    }
end

function HeroManager.getPlayerDrawIsShip()
    if Util.GetPlayerPrefs("drawIsShip") == "true" then
        return true;
    end
    return false;
end

function HeroManager.setPlayerDrawIsShip(flag)
    if Util.GetPlayerPrefs("drawIsShip") ~= flag then
        Util.SetPlayerPrefs("drawIsShip", flag);
    end
end
function HeroManager.ShowUnlockPartner(heroId)
    --showUI(PanelNames.UIDrawAnimation, heroId)
    --local heroData = logicMgr.HeroManager.getHeroDatabyModelId(heroId,true);
    showUI(PanelNames.UIDrawAnimation, heroId, 1, false, function()
        HeroManager.ActivateCB(heroId)
    end, nil, true);
    local data = this.getHeroDatabyModelId(heroId, true)
    if data then
        this.setHeroIsNew(data.partnerId)
    end
end
function HeroManager.ActivateCB(heroId)
    local heroData = logicMgr.HeroManager.getHeroDatabyModelId(heroId)
    if heroData ~= nil then
        if isOpenUI(PanelNames.UIDraw) then
            showUI(PanelNames.UICharactorInfoHero, heroData, 1, true)
        end
    end
    if this.needShowHeroList ~= nil then
        table.remove(this.needShowHeroList, 1);
    end
    closeUI(PanelNames.UIDrawAnimation)
end
--心愿英雄
function HeroManager.SetWishData(msg)
    if msg then
        winshHeroData = {}
        local job = {}
        for k, v in pairs(msg.heroList) do
            job = {}
            job[1] = v.wishHeroId[1] or 0
            job[2] = v.wishHeroId[2] or 0

            winshHeroData[k] = job
        end
        winshHeroData[7] = { msg.bestHeroIds[1] or 0, msg.bestHeroIds[2] or 0 }
        drawCount = msg.optCount
        if this.lastDrawCount == nil then
            this.lastDrawCount = drawCount;
        end
        wishHasNum = msg.acquireBestID or {}
        insureRemain = msg.insureRemain or -1
        this.allVipNum = msg.extraBestHeroTimesCount
        this.hasVipNum = msg.remainExtraBestHeroTimesCount
        this.extraHeros = { msg.extraBestHeroIds[1] or 0, msg.extraBestHeroIds[2] or 0 }
        this.extraNum = msg.extraBestRound
        this.extraHasHeroIds = { msg.extraAcquireBestID[1] or 0, msg.extraAcquireBestID[2] or 0 }
        -- winshHeroData =  msg
        FireEvent(Config.EventType.Draw_Wish_list_Update)
    end
end

--无线
function HeroManager.GetExtraHero()
    return this.extraHeros
end

function HeroManager.WishIsGet(modelId)
    if wishHasNum then
        if modelId and modelId ~= 0 then
            for _, v in pairs(wishHasNum) do
                if v and v == tonumber(modelId) then
                    return true
                end
            end
        else
            if #wishHasNum == 0 or #wishHasNum == 1 then
                return false
            else
                return true
            end
        end
    end
    return false
end

function HeroManager.GetWishNum()
    return drawCount, wishHasNum
end

function HeroManager.GetLastDrawNum()
    return this.lastDrawCount;
end

function HeroManager.SetLastDrawNum(num)
    this.lastDrawCount = num;
end

--上阵英雄是否都已实现
function HeroManager.CheckAllShowHeroGet(heroShowList)
    local isAllGet = true
    for _, v in pairs(heroShowList) do
        if not logicMgr.HeroManager.WishIsGet(v) then
            isAllGet = false
            break
        end
    end
    return isAllGet
end

function HeroManager.GetWishData(isWant)
    if not winshHeroData then
        winshHeroData = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }
    end
    if not isWant then
        return clone(winshHeroData)
    else
        return clone(winshHeroData[7])
    end
end

function HeroManager.CheckWishHeroRedpoint()
    local list = HeroManager.GetWishData()
    for k, v in pairs(list) do
        if k < 7 then
            for _, vv in pairs(v) do
                if vv == 0 then
                    return true
                end
            end
        else
            if k == 7 then
                if drawCount >= G.dataTable["t_global"]["406"].f_int_value then
                    if list[7][1] == 0 or list[7][2] == 0 then
                        return true
                    end
                end
            end
        end
    end
    return false
end

function HeroManager.GetInsureRemain()
    return insureRemain
end

function HeroManager.IsNewHero(poolId, modeld)
    if not poolId then
        poolId = 1
    end
    local config = G.dataTable["t_drawpool"][tostring(poolId)].f_NewHero
    for _, v in ipairs(config) do
        if v == modeld then
            return true
        end
    end
    return false
end
--------热度榜 start
local m_hot_hero_rank = {}
function HeroManager.SetHotHeroRank(msg)
    local version = HeroManager.GetHotHeroRankVersion(msg.rankType)
    if version ~= msg.rankVersion then
        m_hot_hero_rank[msg.rankType] = { list = msg.rankList, version = msg.rankVersion }
    end
end

function HeroManager.GetHotHeroRankVersion(type)
    local version = 0
    if m_hot_hero_rank[type] then
        version = m_hot_hero_rank[type].version
    end
    return version
end

function HeroManager.GetHotHeroRank(type)
    if m_hot_hero_rank[type] == nil then
        m_hot_hero_rank[type] = { version = 0, list = {} }
    end

    return m_hot_hero_rank[type].list
end
--------热度榜 end
---第一个英雄是否克制第二个英雄
function HeroManager.GetHeroRestrain(partnerModelId1, partnerModelId2)
    if partnerModelId1 == nil or partnerModelId2 == nil then
        return false;
    end
    local heroTable1 = this.GetHeroConfigbyModelId(partnerModelId1);
    local heroTable2 = this.GetHeroConfigbyModelId(partnerModelId2);
    if heroTable1 == nil or heroTable2 == nil then
        return false;
    end
    this.heroRestrain = decodeJsonStrToTabel(dataTable.getGlobalString(187))
    return this.heroRestrain[heroTable1.f_HeroType] and this.heroRestrain[heroTable1.f_HeroType][1] == heroTable2.f_HeroType;
end

function HeroManager.getCombinationSkillList(formation)
    local tempList = {};
    local combinationSkillList = {}
    local heroCount = table.getn(formation)
    local tempFormation = clone(formation)

    for i = 1, heroCount do
        if table.getn(tempFormation) > 1 then
            local mainHeroId = table.remove(tempFormation, 1);--直接从队伍列表里面把需要开始索引的英雄拿出来，因为技能是一样的
            local combInfo = combinationShowInfo[tostring(mainHeroId)];
            if combInfo then
                local combHeroIds = clone(combInfo.f_CombinationHero);
                local combinationSkills = clone(combInfo.f_CombinationId);--技能id列表
                --不是神魔羁绊
                local otherHero = {}--势力连结的英雄数据
                if type(combInfo.f_CombinationId2) == "table" then
                    table.insert(combinationSkills, combInfo.f_CombinationId2[1])
                    table.insert(combHeroIds, {})
                end
                for combIdx, v in ipairs(combHeroIds) do
                    local satisfyCount = table.getn(v);--获取需要满足条件的人数
                    local count = 0;
                    local mainHerType = heroCfg[tostring(mainHeroId)].f_FactionType;--主英雄势力类型 1神 2魔
                    local skill = combinationSkills[combIdx];

                    if satisfyCount == 0 and (mainHerType == 1 or mainHerType == 2 or mainHerType == 3) then
                        --神魔羁绊
                        local cfg = nil
                        if type(combinationInfo[tostring(skill)].f_CombinationFaction) == "table" and table.getn(combinationInfo[tostring(skill)].f_CombinationFaction) > 0 then
                            cfg = combinationInfo[tostring(skill)].f_CombinationFaction
                            satisfyCount = cfg[2]
                            if table.getn(tempFormation) + 1 >= satisfyCount and mainHerType == cfg[1] then
                                count = 1;--因为4个神魔包括主索引英雄本身
                                for teamIdx, teamHeroId in pairs(tempFormation) do
                                    local heroCfgInfo = heroCfg[tostring(teamHeroId)];
                                    if heroCfgInfo ~= nil then
                                        local heroCfgType = heroCfgInfo.f_FactionType;
                                        if (mainHerType == 1 and heroCfgType == 1) or (mainHerType == 2 and heroCfgType == 2) or (mainHerType == 3 and heroCfgType == 3) then
                                            table.insert(otherHero, teamHeroId);
                                            count = count + 1;
                                        end
                                    end
                                end
                                if count == satisfyCount then
                                    --满足激活条件
                                    local param = {}
                                    if skill and combinationInfo[tostring(skill)].f_Block ~= 1 then
                                        param.skillId = skill;
                                        param.decs = combinationInfo[tostring(skill)].f_CombinationSkillDesc;--技能描述
                                        local heros = otherHero;
                                        table.insert(heros, 1, mainHeroId)
                                        param.heroIds = heros;
                                        tempList[param.skillId] = param;
                                    end
                                end
                            end
                        end
                    else
                        --非神魔羁绊
                        local combHeroItem = {}
                        for index, heroId in pairs(v) do
                            combHeroItem[heroId] = true;
                        end
                        for teamIdx, teamHeroId in pairs(tempFormation) do
                            if combHeroItem[tonumber(teamHeroId)] then
                                count = count + 1;
                            end
                        end
                        if count == satisfyCount then
                            --满足激活条件
                            local param = {}
                            if skill and combinationInfo[tostring(skill)].f_Block ~= 1 then
                                param.skillId = skill;
                                param.decs = combinationInfo[tostring(skill)].f_CombinationSkillDesc;--技能描述
                                local heros = clone(v)
                                table.insert(heros, 1, mainHeroId)
                                param.heroIds = heros;
                                tempList[param.skillId] = param;
                            end
                        end
                    end
                end
            else
                --printError("英雄id"..mainHeroId.."没有羁绊技能");
            end
        end
    end
    for i, v in pairs(tempList) do
        table.insert(combinationSkillList, v);
    end

    return combinationSkillList
end

function HeroManager.getCombinationInfo(id)
    if id == nil then
        return combinationInfo;
    end
    return combinationInfo[tostring(id)];
end

function HeroManager.getCombinationShowInfo()
    return combinationShowInfo or {};
end

--头像框改变更新属性
function HeroManager.RefreshHeadFrameAtt()
    local fetterAttrList = {}
    local frame = G.serverData["roleInfo"].show.picFrame
    local config = G.dataTable["t_headframe"][tostring(frame)]
    if config then
        local tb = config.f_CharacterValue
        if type(tb) == "table" then
            for k, v in pairs(tb) do
                fetterAttrList[v[1]] = v[2]
            end
        end
    end

    for _, heroInfo in pairs(tabAllHero) do
        heroInfo.allAttribute[EnumConst.AttributeTypeEnum.HEAD_FRAME] = fetterAttrList
        this.processHeroAllAttr(heroInfo);
    end
end

--徽章激活更新属性
function HeroManager.RefreshBadgeAtt()
    local allAttr = logicMgr.TitleManager.GetAllAttr()   --已经激活的徽章
    for _, heroInfo in pairs(tabAllHero) do
        heroInfo.allAttribute[EnumConst.AttributeTypeEnum.Badge] = allAttr
        this.processHeroAllAttr(heroInfo);
    end
    partnerHandler.ReqHeroPower(0)
end

--设置己方英雄列表skinId(正在穿的skinId)
function HeroManager.SetMyHeroSkin(heroList)
    if heroList then
        for _, v in pairs(heroList) do
            local heroModelId = v["partnerModelId"] or v["f_HeroID"] or 0
            local heroUseSkinId = logicMgr.SkinManager.getHeroSkinId(heroModelId)
            if heroUseSkinId and heroUseSkinId > 0 then
                v.skinId = heroUseSkinId
            end
        end
    end
end

--设置己方单个英雄skinId(正在穿的skinId)
function HeroManager.SetMyOneHeroSkin(oneHero)
    if oneHero then
        local heroModelId = oneHero["partnerModelId"] or oneHero["f_HeroID"] or 0
        local heroUseSkinId = logicMgr.SkinManager.getHeroSkinId(heroModelId)
        if heroUseSkinId and heroUseSkinId > 0 then
            oneHero.skinId = heroUseSkinId
        end
    end
end
---------------------------------阵容推荐---开始-----------------
--获取阵容推荐表格数据
function HeroManager.getFormationTableData(id)
    if id == nil then
        if this.formationTableList == nil then
            this.formationTableList = {};
            for k, v in pairs(G.dataTable["t_battlerecommed"]) do
                v.f_TeamHero = decodeJsonStrToTabel(v.f_TeamHero);
                table.insert(this.formationTableList, v);
            end
            table.sort(this.formationTableList, function(a, b)
                return a.f_TeamId < b.f_TeamId;
            end)
        end
        return this.formationTableList;
    end
    return G.dataTable["t_battlerecommed"][tostring(id)];
end
--获取阵容推荐任务表格数据
function HeroManager.getFormationTaskTableData(id)
    if id == nil then
        return G.dataTable["t_battletask"];
    end
    return G.dataTable["t_battletask"][tostring(id)];
end

--获取推荐阵容任务完成情况 0:未完成, 1:已完成未领取, 2:已领取
function HeroManager.getFormationRecTaskStateById(id)
    local data = {};
    if id == nil then
        data.state = 2;
        return data;
    end
    local taskTable = this.getFormationTaskTableData(id);
    if taskTable == nil then
        data.state = 2;
        return data, taskTable;
    end
    if taskTable.f_TaskType == 1 then
        data = this.getTelevationTaskState(decodeJsonStrToTabel(taskTable.f_Parameter), taskTable.f_TeamId);
    end
    return data, taskTable;
end
function HeroManager.getTelevationTaskState(taskData, teamId)
    local data = {};
    local teamTable = this.getFormationTableData(teamId);
    if teamTable == nil then
        data.state = 2;
        return data;
    end
    data.max = taskData[2]
    data.progress = 0
    data.state = 0
    local _data = {};
    local teamList = decodeJsonStrToTabel(teamTable.f_TeamHero);
    for k, v in pairs(teamList) do
        if logicMgr.HeroManager.IsHaveByPartnerModelId(v[1]) then
            _data = logicMgr.HeroManager.getHeroDatabyModelId(v[1]);
            if _data.star >= taskData[1] then
                data.progress = data.progress + 1;
            end
        end
    end
    if data.progress >= data.max then
        data.state = 1;
    end
    return data;
end

--设置阵容推荐数据
function HeroManager.setFormationRecInfo(data)
    this.formationRecClickList = {};
    this.formationRecTaskList = {};
    for k, v in pairs(data) do
        this.formationRecClickList[v.formationId] = v.click;
        this.formationRecTaskList[v.formationId] = v.taskId;
    end
end
--设置阵容推荐点赞情况
function HeroManager.setFormationRecClicked(data)
    this.formationRecClickedList = {};
    for k, v in pairs(data) do
        this.formationRecClickedList[v] = true;
    end
end
--更新阵容推荐点赞情况
function HeroManager.updateFormationRecClickedById(id)
    this.formationRecClickedList = this.formationRecClickedList or {};
    this.formationRecClickedList[tonumber(id)] = true;
end
--更新推荐阵容点赞数
function HeroManager.updateFormationRecClickById(id, data)
    this.formationRecClickList = this.formationRecClickList or {};
    this.formationRecClickList[tonumber(id)] = data
end
--更新推荐阵容当前任务id
function HeroManager.updateFormationRecTaskById(id, data)
    this.formationRecTaskList = this.formationRecTaskList or {};
    this.formationRecTaskList[tonumber(id)] = data;
end
--获取推荐阵容点赞数
function HeroManager.getFormationRecClickById(id)
    this.formationRecClickList = this.formationRecClickList or {};
    if id == nil then
        return this.formationRecClickList;
    end
    return this.formationRecClickList[tonumber(id)] or 0;
end
--获取推荐阵容当前任务id
function HeroManager.getFormationRecTaskById(id)
    this.formationRecTaskList = this.formationRecTaskList or {};
    if id == nil then
        return this.formationRecTaskList;
    end
    return this.formationRecTaskList[tonumber(id)] or 0;
end
--获取推荐阵容点赞情况
function HeroManager.getFormationRecClickedById(id)
    this.formationRecClickedList = this.formationRecClickedList or {};
    if id == nil then
        return this.formationRecClickedList;
    end
    return this.formationRecClickedList[tonumber(id)];
end
---------------------------------阵容推荐---结束-----------------
function HeroManager.setCharactorParameter(...)
    this.charactorParameter = { ... };
end
function HeroManager.getCharactorParameter()
    this.charactorParameter = this.charactorParameter or {};
    return this.charactorParameter[1], this.charactorParameter[2], this.charactorParameter[3], this.charactorParameter[4], this.charactorParameter[5], this.charactorParameter[6];
end
function HeroManager.GetSuit(equips, tagEquip)
    if equips == nil or tagEquip == nil or tagEquip["suit"] == 0 then
        return 0
    end

    local count = 0
    for _, info in pairs(equips) do
        local suitValue = info["suit"]
        if suitValue > 0 and tagEquip["suit"] == suitValue then
            count = count + 1
        end
    end
    if count >= 2 then
        return tagEquip.suit
    end
    return 0
end

-------------------------------英雄置换---开始---------------------
--设置置换英雄的modelId
function HeroManager.setSwapHeros(index, heroModelId)
    if index ~= nil then
        index = tonumber(index)
        if this.swapHeros == nil then
            this.swapHeros = {}
        end
        this.swapHeros[index] = heroModelId
    end
end

function HeroManager.getSwapHeros()
    return this.swapHeros or {}
end

--设置当前英雄置换是否需要预览
function HeroManager.setHeroSwapHasPreviewed(hasPreviewed)
    this.heroSwapHasPreviewed = hasPreviewed
end

function HeroManager.getHeroSwapHasPreviewed()
    return this.heroSwapHasPreviewed
end

--计算英雄重生返还的材料
function HeroManager.getHeroRebornReturn(heroModelId)
    local dataItems = {}
    local currentData = logicMgr.HeroManager.getHeroDatabyModelId(heroModelId)
    dataItems[CurrencyEnum.HeroExp] = 0
    for i = 1, currentData.level - 1 do
        dataItems[CurrencyEnum.HeroExp] = dataItems[CurrencyEnum.HeroExp] + charactorExpConfig[MakeTopLevelId(i)]["f_HeroExp"]
        local costArray = decodeJsonStrToTabel(charactorExpConfig[MakeTopLevelId(i)]["f_HeroCost"])
        for k = 1, #costArray do
            local costItem = costArray[k]
            if dataItems[costItem[1]] ~= nil then
                dataItems[costItem[1]] = dataItems[costItem[1]] + costItem[2]
            else
                dataItems[costItem[1]] = costItem[2];
            end
        end
    end
    if dataItems[CurrencyEnum.HeroExp] == 0 then
        dataItems[CurrencyEnum.HeroExp] = nil
    end
    return dataItems
end

--设置当前英雄置换的返还材料
function HeroManager.setHeroSwapCost(itemList)
    this.heroSwapCostItemList = itemList
end

--获取当前英雄置换的返还材料
function HeroManager.getHeroSwapCost()
    return this.heroSwapCostItemList
end

--获取当前英雄置换的返还材料
function HeroManager.clearHeroSwapData()
    this.swapHeros = nil
    this.heroSwapHasPreviewed = false
    this.heroSwapCostItemList = nil
end

-------------------------------英雄置换---结束---------------------
---设置在线时长,并开始倒计时
function HeroManager.setOnlineTime(time)
    this.onlineTime = time or 0;
    --this.onlineNowTime = HelperFunc.GetServerTime()
    --logError("当前在线时长"..this.onlineTime)
    this.beginOnlineTime(true);
end

--获取在线时长(实时)
function HeroManager.beginOnlineTime(isBegin)
    if this.utimeOnline then
        utimer.remove(this.utimeOnline);
        this.utimeOnline = nil;
    end
    if not isBegin then
        return ;
    end
    this.utimeOnline = utimer.timeCall(function()
        this.onlineTime = this.onlineTime + 1;
        --if this.OnlineTimeNode and this.OnlineTimeNode.time <= this.onlineTime + HelperFunc.GetServerTime() - this.onlineNowTime then
        if this.OnlineTimeNode and this.OnlineTimeNode.time <= this.onlineTime then
            local _callBack = this.OnlineTimeNode.callback;
            this.OnlineTimeNode = nil;
            if _callBack then
                _callBack();
            end
        end
    end, 1000, -1);
end
--获取在线时长(实时)
function HeroManager.getOnlineTime()
    --return (this.onlineTime or 0) + HelperFunc.GetServerTime() - this.onlineNowTime
    return (this.onlineTime or 0)
end

function HeroManager.setOnlineTimeNode(time, callback)
    if time == nil then
        return ;
    end
    this.OnlineTimeNode = {};
    this.OnlineTimeNode.time = time;
    this.OnlineTimeNode.callback = callback;
end

--- 设置抽卡每日已抽次数
function HeroManager.setDrawTodayCount(key, count, time)
    if key == nil then
        return ;
    end
    key = tostring(key)
    count = count or 0;
    time = time or HelperFunc.GetServerTime();
    time = time - 5 * 3600
    time = os.date("%Y.%m.%d", time);
    this.drawTodayCountList = this.drawTodayCountList or {};
    this.drawTodayCountList[key] = {};
    this.drawTodayCountList[key].time = time;
    this.drawTodayCountList[key].count = count;
end
--- 获取抽卡每日已抽次数
function HeroManager.getDrawTodayCount(key, time)
    if key == nil then
        return 0;
    end
    key = tostring(key)
    this.drawTodayCountList = this.drawTodayCountList or {};
    if this.drawTodayCountList[key] == nil then
        return 0;
    end
    time = time or HelperFunc.GetServerTime();
    time = time - 5 * 3600
    time = os.date("%Y.%m.%d", time);
    if this.drawTodayCountList[key].time == time then
        return this.drawTodayCountList[key].count;
    end
    return 0;
end
---
function HeroManager.setChooseHeroById(data)
    this.chooseHeroList = data;
    this.chooseHeroMap = nil;
end
---
function HeroManager.getChooseHeroById(type)
    if this.chooseHeroMap == nil then
        this.chooseHeroList = this.chooseHeroList or {};
        this.chooseHeroMap = {};
        for k, v in pairs(this.chooseHeroList) do
            this.chooseHeroMap[v.type] = this.chooseHeroMap[v.type] or {};
            for k1, v1 in pairs(v.heroAiList) do
                this.chooseHeroMap[v.type][v1.heroId] = this.chooseHeroMap[v.type][v1.heroId] or {};
                for k2, v2 in pairs(v1.skillList) do
                    this.chooseHeroMap[v.type][v1.heroId][v2.skillType] = this.chooseHeroMap[v.type][v1.heroId][v2.skillType] or {};
                    this.chooseHeroMap[v.type][v1.heroId][v2.skillType][v2.conditionType] = v2.paramValue;
                end
            end
        end
        dump(this.chooseHeroMap, "技能接收 ")
    end
    this.chooseHeroMap[type] = this.chooseHeroMap[type] or {};
    return this.chooseHeroMap[type];
end
---
function HeroManager.isShowChooseByType(type)
    if type == nil then
        return ;
    end
    if this.notShowHeroChooseFightTypeMap[type] then
        return ;
    end
    return true;
end

--- 看板娘相关数据
function HeroManager.setShowFemaleRole(id)
    if not G.serverData['sideGirl'] then
        G.serverData['sideGirl'] = {}
    end
    G.serverData['sideGirl']['showFemaleRole'] = id
end
function HeroManager.getShowFemaleRole()
    if G.serverData['sideGirl'] and G.serverData['sideGirl']['showFemaleRole'] then
        return G.serverData['sideGirl']['showFemaleRole']
    end
    return 1001
end
function HeroManager.setShowTravelFemaleRole(id)
    if not G.serverData['sideGirl'] then
        G.serverData['sideGirl'] = {}
    end
    G.serverData['sideGirl']['showTravelFemaleRole'] = id
end
function HeroManager.getShowTravelFemaleRole()
    if G.serverData['sideGirl'] and G.serverData['sideGirl']['showTravelFemaleRole'] then
        return G.serverData['sideGirl']['showTravelFemaleRole']
    end
    return 1002
end

--- 主城背景
function HeroManager.getCityBackground()
    return G.serverData['cityBg'] or 1001
end

return HeroManager